summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml2
-rw-r--r--README.md5
-rw-r--r--SConstruct146
-rw-r--r--bin/tests/test_gdscript.cpp20
-rw-r--r--bin/tests/test_gui.cpp4
-rw-r--r--bin/tests/test_math.cpp1
-rw-r--r--core/SCsub2
-rw-r--r--core/bind/core_bind.cpp77
-rw-r--r--core/bind/core_bind.h26
-rw-r--r--core/color.cpp2
-rw-r--r--core/dictionary.cpp2
-rw-r--r--core/globals.cpp8
-rw-r--r--core/image.cpp29
-rw-r--r--core/image.h14
-rw-r--r--core/int_types.h2
-rw-r--r--core/io/config_file.cpp9
-rw-r--r--core/io/http_client.cpp2
-rw-r--r--core/io/ip.cpp2
-rw-r--r--core/io/ip_address.h6
-rw-r--r--core/io/json.cpp2
-rw-r--r--core/io/object_format_binary.cpp1491
-rw-r--r--core/io/object_format_binary.h158
-rw-r--r--core/io/object_format_xml.cpp3190
-rw-r--r--core/io/object_format_xml.h196
-rw-r--r--core/io/object_loader.cpp84
-rw-r--r--core/io/object_loader.h76
-rw-r--r--core/io/object_saver.cpp157
-rw-r--r--core/io/object_saver.h128
-rw-r--r--core/io/object_saver_base.cpp150
-rw-r--r--core/io/packet_peer.cpp2
-rw-r--r--core/io/packet_peer_udp.cpp63
-rw-r--r--core/io/packet_peer_udp.h37
-rw-r--r--core/io/resource_format_xml.cpp8
-rw-r--r--core/io/stream_peer_tcp.cpp2
-rw-r--r--core/io/xml_parser.cpp4
-rw-r--r--core/math/geometry.cpp131
-rw-r--r--core/math/geometry.h57
-rw-r--r--core/math/math_funcs.cpp2
-rw-r--r--core/math/math_funcs.h6
-rw-r--r--core/math/quick_hull.cpp3
-rw-r--r--core/method_bind.cpp4
-rw-r--r--core/method_bind.h1
-rw-r--r--core/object.cpp7
-rw-r--r--core/object.h2
-rw-r--r--core/object_type_db.cpp40
-rw-r--r--core/object_type_db.h4
-rw-r--r--core/os/input.cpp25
-rw-r--r--core/os/input.h2
-rw-r--r--core/os/input_event.cpp4
-rw-r--r--core/os/input_event.h2
-rw-r--r--core/os/keyboard.cpp105
-rw-r--r--core/os/keyboard.h1
-rw-r--r--core/os/os.cpp13
-rw-r--r--core/os/os.h29
-rw-r--r--core/register_core_types.cpp38
-rw-r--r--core/script_language.cpp7
-rw-r--r--core/script_language.h4
-rw-r--r--core/translation.cpp74
-rw-r--r--core/typedefs.h2
-rw-r--r--core/undo_redo.cpp5
-rw-r--r--core/ustring.cpp50
-rw-r--r--core/ustring.h3
-rw-r--r--core/variant.cpp126
-rw-r--r--core/variant.h10
-rw-r--r--core/variant_call.cpp35
-rw-r--r--core/variant_op.cpp36
-rw-r--r--demos/2d/hexamap/.fscache33
-rw-r--r--demos/2d/hexamap/WWT-01.pngbin0 -> 20369 bytes
-rw-r--r--demos/2d/hexamap/WWT-02.pngbin0 -> 21993 bytes
-rw-r--r--demos/2d/hexamap/WWT-03.pngbin0 -> 22703 bytes
-rw-r--r--demos/2d/hexamap/WWT-04.pngbin0 -> 20615 bytes
-rw-r--r--demos/2d/hexamap/WWT-05.pngbin0 -> 22293 bytes
-rw-r--r--demos/2d/hexamap/WWT-06.pngbin0 -> 22971 bytes
-rw-r--r--demos/2d/hexamap/WWT-07.pngbin0 -> 22306 bytes
-rw-r--r--demos/2d/hexamap/WWT-08.pngbin0 -> 22084 bytes
-rw-r--r--demos/2d/hexamap/WWT-09.pngbin0 -> 22066 bytes
-rw-r--r--demos/2d/hexamap/WWT-10.pngbin0 -> 22019 bytes
-rw-r--r--demos/2d/hexamap/WWT-11.pngbin0 -> 21546 bytes
-rw-r--r--demos/2d/hexamap/WWT-12.pngbin0 -> 21405 bytes
-rw-r--r--demos/2d/hexamap/WWT-13.pngbin0 -> 19682 bytes
-rw-r--r--demos/2d/hexamap/WWT-14.pngbin0 -> 20491 bytes
-rw-r--r--demos/2d/hexamap/WWT-15.pngbin0 -> 21237 bytes
-rw-r--r--demos/2d/hexamap/WWT-16.pngbin0 -> 20673 bytes
-rw-r--r--demos/2d/hexamap/WWT-17.pngbin0 -> 20628 bytes
-rw-r--r--demos/2d/hexamap/WWT-18.pngbin0 -> 22559 bytes
-rw-r--r--demos/2d/hexamap/WWT-19.pngbin0 -> 21600 bytes
-rw-r--r--demos/2d/hexamap/WWT-20.pngbin0 -> 21130 bytes
-rw-r--r--demos/2d/hexamap/WWT-21.pngbin0 -> 21114 bytes
-rw-r--r--demos/2d/hexamap/WWT-22.pngbin0 -> 21440 bytes
-rw-r--r--demos/2d/hexamap/WWT-23.pngbin0 -> 20817 bytes
-rw-r--r--demos/2d/hexamap/WWT-24.pngbin0 -> 19964 bytes
-rw-r--r--demos/2d/hexamap/WWT-25.pngbin0 -> 20584 bytes
-rw-r--r--demos/2d/hexamap/WWT-26.pngbin0 -> 21405 bytes
-rw-r--r--demos/2d/hexamap/engine.cfg12
-rw-r--r--demos/2d/hexamap/icon.pngbin0 -> 5925 bytes
-rw-r--r--demos/2d/hexamap/map.scnbin0 -> 2644 bytes
-rw-r--r--demos/2d/hexamap/tiles.scnbin0 -> 2091 bytes
-rw-r--r--demos/2d/hexamap/tileset.resbin0 -> 6863 bytes
-rw-r--r--demos/2d/hexamap/troll.gd43
-rw-r--r--demos/2d/hexamap/troll.pngbin0 -> 7246 bytes
-rw-r--r--demos/2d/hexamap/troll.scnbin0 -> 1839 bytes
-rw-r--r--demos/2d/isometric/bastiles.resbin0 -> 1840 bytes
-rw-r--r--demos/2d/isometric/dungeon.scnbin0 -> 4582 bytes
-rw-r--r--demos/2d/isometric/engine.cfg21
-rw-r--r--demos/2d/isometric/icon.pngbin0 -> 9377 bytes
-rw-r--r--demos/2d/isometric/isotiles.pngbin0 -> 222339 bytes
-rw-r--r--demos/2d/isometric/tileset.scnbin0 -> 2305 bytes
-rw-r--r--demos/2d/isometric/troll.gd43
-rw-r--r--demos/2d/isometric/troll.pngbin0 -> 7246 bytes
-rw-r--r--demos/2d/isometric/troll.scnbin0 -> 1839 bytes
-rw-r--r--demos/2d/kinematic_char/colworld.scnbin5090 -> 6367 bytes
-rw-r--r--demos/2d/kinematic_char/player.gd8
-rw-r--r--demos/2d/kinematic_char/player.scnbin1511 -> 1728 bytes
-rw-r--r--demos/2d/platformer/player.gd3
-rw-r--r--demos/2d/platformer/player.xml173
-rw-r--r--demos/2d/platformer/stage.xml681
-rw-r--r--demos/2d/shower_of_bullets/bullet.pngbin0 -> 477 bytes
-rw-r--r--demos/2d/shower_of_bullets/bullets.gd76
-rw-r--r--demos/2d/shower_of_bullets/engine.cfg16
-rw-r--r--demos/2d/shower_of_bullets/face_happy.pngbin0 -> 1243 bytes
-rw-r--r--demos/2d/shower_of_bullets/face_sad.pngbin0 -> 1240 bytes
-rw-r--r--demos/2d/shower_of_bullets/icon.pngbin0 -> 2777 bytes
-rw-r--r--demos/2d/shower_of_bullets/shower.gd32
-rw-r--r--demos/2d/shower_of_bullets/shower.scnbin0 -> 1836 bytes
-rw-r--r--demos/3d/kinematic_char/cubio.gd2
-rw-r--r--demos/3d/mousepick_test/mousepick.gd2
-rw-r--r--demos/3d/navmesh/engine.cfg9
-rw-r--r--demos/3d/navmesh/navmesh.gd110
-rw-r--r--demos/3d/navmesh/navmesh.scnbin0 -> 37856 bytes
-rw-r--r--demos/3d/navmesh/particle.pngbin0 -> 260 bytes
-rw-r--r--demos/3d/platformer/texture.texbin29600 -> 18209 bytes
-rw-r--r--demos/3d/platformer/tiles.resbin81338 -> 81631 bytes
-rw-r--r--demos/3d/truck_town/car_base.scnbin0 -> 11573 bytes
-rw-r--r--demos/3d/truck_town/car_select.gd42
-rw-r--r--demos/3d/truck_town/car_select.scnbin0 -> 1702 bytes
-rw-r--r--demos/3d/truck_town/cement.texbin0 -> 169836 bytes
-rw-r--r--demos/3d/truck_town/choose_tow.pngbin0 -> 20702 bytes
-rw-r--r--demos/3d/truck_town/choose_trailer.pngbin0 -> 15646 bytes
-rw-r--r--demos/3d/truck_town/choose_van.pngbin0 -> 10106 bytes
-rw-r--r--demos/3d/truck_town/crane.scnbin0 -> 24164 bytes
-rw-r--r--demos/3d/truck_town/engine.cfg12
-rw-r--r--demos/3d/truck_town/follow_camera.gd69
-rw-r--r--demos/3d/truck_town/grass.texbin0 -> 177762 bytes
-rw-r--r--demos/3d/truck_town/trailer_truck.scnbin0 -> 19934 bytes
-rw-r--r--demos/3d/truck_town/truck_scene.scnbin0 -> 1873575 bytes
-rw-r--r--demos/3d/truck_town/trucktown.scnbin0 -> 161749 bytes
-rw-r--r--demos/3d/truck_town/vehicle.gd54
-rw-r--r--demos/misc/autoload/global.gd9
-rw-r--r--demos/misc/pause/spinpause.gd4
-rw-r--r--demos/misc/tween/icon.pngbin0 -> 3621 bytes
-rw-r--r--demos/misc/tween/main.gd4
-rw-r--r--demos/misc/udp_chat/chat.gd72
-rw-r--r--demos/misc/udp_chat/chat.scnbin0 -> 3198 bytes
-rw-r--r--demos/misc/udp_chat/engine.cfg5
-rw-r--r--demos/misc/udp_chat/icon.pngbin0 -> 2388 bytes
-rw-r--r--doc/base/classes.xml7846
-rw-r--r--drivers/SCsub3
-rw-r--r--drivers/builtin_openssl2/openssl/md5.h4
-rw-r--r--drivers/chibi/cp_loader_s3m.cpp2
-rw-r--r--drivers/gl_context/context_gl.cpp2
-rw-r--r--drivers/gl_context/context_gl.h2
-rw-r--r--drivers/gles1/rasterizer_gles1.cpp5957
-rw-r--r--drivers/gles1/rasterizer_gles1.h1242
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp1192
-rw-r--r--drivers/gles2/rasterizer_gles2.h54
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp104
-rw-r--r--drivers/gles2/shader_compiler_gles2.h11
-rw-r--r--drivers/gles2/shaders/canvas.glsl136
-rw-r--r--drivers/gles2/shaders/copy.glsl20
-rw-r--r--drivers/gles2/shaders/material.glsl73
-rw-r--r--drivers/mpc/audio_stream_mpc.cpp10
-rw-r--r--drivers/ogg/SCsub3
-rw-r--r--drivers/png/image_loader_png.cpp3
-rw-r--r--drivers/png/pngpriv.h6
-rw-r--r--drivers/png/resource_saver_png.cpp72
-rw-r--r--drivers/png/resource_saver_png.h4
-rw-r--r--drivers/pulseaudio/SCsub (renamed from drivers/gles1/SCsub)2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp194
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h (renamed from core/io/object_saver_base.h)65
-rw-r--r--drivers/squish/image_compress_squish.cpp17
-rw-r--r--drivers/theora/SCsub3
-rw-r--r--drivers/theoraplayer/SCsub30
-rw-r--r--drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h2
-rw-r--r--drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h4
-rw-r--r--drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm5
-rw-r--r--drivers/theoraplayer/src/TheoraVideoClip.cpp5
-rw-r--r--drivers/theoraplayer/src/TheoraVideoManager.cpp14
-rw-r--r--drivers/theoraplayer/video_stream_theoraplayer.cpp193
-rw-r--r--drivers/theoraplayer/video_stream_theoraplayer.h10
-rw-r--r--drivers/unix/ip_unix.cpp2
-rw-r--r--drivers/unix/memory_pool_static_malloc.cpp8
-rw-r--r--drivers/unix/os_unix.cpp8
-rw-r--r--drivers/unix/packet_peer_udp_posix.cpp194
-rw-r--r--drivers/unix/packet_peer_udp_posix.h57
-rw-r--r--drivers/vorbis/SCsub6
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--drivers/vorbis/os.h2
-rw-r--r--drivers/webp/dsp/dsp.h2
-rw-r--r--drivers/webp/utils/bit_reader.h1
-rw-r--r--drivers/windows/dir_access_windows.cpp19
-rw-r--r--drivers/windows/file_access_windows.cpp1
-rw-r--r--main/SCsub2
-rw-r--r--main/main.cpp43
-rw-r--r--main/performance.cpp2
-rw-r--r--makefile30
-rwxr-xr-xmethods.py55
-rw-r--r--modules/SCsub2
-rw-r--r--modules/gdscript/gd_compiler.cpp94
-rw-r--r--modules/gdscript/gd_compiler.h4
-rw-r--r--modules/gdscript/gd_editor.cpp1637
-rw-r--r--modules/gdscript/gd_functions.cpp4
-rw-r--r--modules/gdscript/gd_parser.cpp474
-rw-r--r--modules/gdscript/gd_parser.h64
-rw-r--r--modules/gdscript/gd_script.cpp217
-rw-r--r--modules/gdscript/gd_script.h45
-rw-r--r--modules/gdscript/gd_tokenizer.cpp40
-rw-r--r--modules/gdscript/gd_tokenizer.h9
-rw-r--r--modules/gdscript/register_types.cpp6
-rw-r--r--modules/gridmap/grid_map.cpp4
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp24
-rw-r--r--modules/gridmap/register_types.cpp4
-rw-r--r--platform/android/SCsub4
-rw-r--r--platform/android/detect.py35
-rw-r--r--platform/android/export/export.cpp46
-rw-r--r--platform/android/globals/global_defaults.cpp2
-rw-r--r--platform/android/java/src/com/android/godot/Godot.java2
-rw-r--r--platform/android/java/src/com/android/godot/GodotIO.java74
-rw-r--r--platform/android/java_glue.cpp20
-rw-r--r--platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java2
-rw-r--r--platform/android/os_android.cpp20
-rw-r--r--platform/android/os_android.h13
-rw-r--r--platform/flash/SCsub1
-rw-r--r--platform/flash/detect.py1
-rw-r--r--platform/iphone/SCsub13
-rw-r--r--platform/iphone/app_delegate.h4
-rw-r--r--platform/iphone/app_delegate.mm18
-rw-r--r--platform/iphone/detect.py69
-rwxr-xr-xplatform/iphone/gl_view.h8
-rwxr-xr-xplatform/iphone/gl_view.mm143
-rw-r--r--platform/iphone/os_iphone.cpp76
-rw-r--r--platform/iphone/os_iphone.h4
-rw-r--r--platform/iphone/platform_config.h3
-rw-r--r--platform/iphone/platform_refcount.h18
-rw-r--r--platform/isim/SCsub11
-rw-r--r--platform/isim/detect.py26
-rw-r--r--platform/javascript/SCsub4
-rw-r--r--platform/javascript/detect.py11
-rw-r--r--platform/nacl/os_nacl.cpp2
-rw-r--r--platform/osx/SCsub2
-rw-r--r--platform/osx/audio_driver_osx.cpp37
-rw-r--r--platform/osx/audio_driver_osx.h4
-rw-r--r--platform/osx/detect.py20
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm113
-rw-r--r--platform/server/detect.py38
-rw-r--r--platform/windows/SCsub3
-rw-r--r--platform/windows/detect.py142
-rw-r--r--platform/windows/os_windows.cpp64
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--platform/windows/packet_peer_udp_winsock.cpp202
-rw-r--r--platform/windows/packet_peer_udp_winsock.h56
-rw-r--r--platform/windows/platform_config.h2
-rw-r--r--platform/winrt/SCsub5
-rw-r--r--platform/winrt/app.cpp385
-rw-r--r--platform/winrt/app.h61
-rw-r--r--platform/winrt/detect.py125
-rw-r--r--platform/winrt/gl_context_egl.cpp177
-rw-r--r--platform/winrt/gl_context_egl.h45
-rw-r--r--platform/winrt/include/EGL/eglext.h21
-rw-r--r--platform/winrt/include/EGL/eglplatform.h4
-rw-r--r--platform/winrt/include/GLSLANG/ShaderLang.h216
-rw-r--r--platform/winrt/include/GLSLANG/ShaderVars.h93
-rw-r--r--platform/winrt/include/angle_windowsstore.h37
-rw-r--r--platform/winrt/os_winrt.cpp222
-rw-r--r--platform/winrt/os_winrt.h14
-rw-r--r--platform/x11/SCsub2
-rw-r--r--platform/x11/detect.py81
-rw-r--r--platform/x11/os_x11.cpp93
-rw-r--r--platform/x11/os_x11.h12
-rw-r--r--platform/x11/platform_config.h2
-rw-r--r--scene/2d/animated_sprite.cpp7
-rw-r--r--scene/2d/area_2d.cpp112
-rw-r--r--scene/2d/area_2d.h19
-rw-r--r--scene/2d/camera_2d.cpp16
-rw-r--r--scene/2d/canvas_item.cpp149
-rw-r--r--scene/2d/canvas_item.h23
-rw-r--r--scene/2d/collision_object_2d.cpp12
-rw-r--r--scene/2d/collision_polygon_2d.cpp24
-rw-r--r--scene/2d/collision_polygon_2d.h4
-rw-r--r--scene/2d/collision_shape_2d.cpp4
-rw-r--r--scene/2d/joints_2d.cpp10
-rw-r--r--scene/2d/node_2d.cpp46
-rw-r--r--scene/2d/node_2d.h7
-rw-r--r--scene/2d/parallax_background.cpp6
-rw-r--r--scene/2d/parallax_layer.cpp6
-rw-r--r--scene/2d/particles_2d.cpp88
-rw-r--r--scene/2d/particles_2d.h14
-rw-r--r--scene/2d/path_2d.cpp8
-rw-r--r--scene/2d/physics_body_2d.cpp178
-rw-r--r--scene/2d/physics_body_2d.h33
-rw-r--r--scene/2d/polygon_2d.cpp1
-rw-r--r--scene/2d/position_2d.cpp6
-rw-r--r--scene/2d/ray_cast_2d.cpp12
-rw-r--r--scene/2d/remote_transform_2d.cpp8
-rw-r--r--scene/2d/remote_transform_2d.h2
-rw-r--r--scene/2d/sample_player_2d.cpp3
-rw-r--r--scene/2d/screen_button.cpp22
-rw-r--r--scene/2d/sound_player_2d.cpp4
-rw-r--r--scene/2d/sprite.cpp26
-rw-r--r--scene/2d/tile_map.cpp224
-rw-r--r--scene/2d/tile_map.h48
-rw-r--r--scene/2d/visibility_notifier_2d.cpp20
-rw-r--r--scene/2d/y_sort.cpp29
-rw-r--r--scene/2d/y_sort.h17
-rw-r--r--scene/3d/SCsub1
-rw-r--r--scene/3d/area.cpp87
-rw-r--r--scene/3d/area.h14
-rw-r--r--scene/3d/baked_light_instance.cpp78
-rw-r--r--scene/3d/baked_light_instance.h42
-rw-r--r--scene/3d/body_shape.cpp28
-rw-r--r--scene/3d/body_shape.h6
-rw-r--r--scene/3d/bone_attachment.cpp8
-rw-r--r--scene/3d/camera.cpp117
-rw-r--r--scene/3d/camera.h11
-rw-r--r--scene/3d/car_body.cpp741
-rw-r--r--scene/3d/car_body.h170
-rw-r--r--scene/3d/collision_object.cpp67
-rw-r--r--scene/3d/collision_object.h9
-rw-r--r--scene/3d/collision_polygon.cpp2
-rw-r--r--scene/3d/editable_shape.cpp85
-rw-r--r--scene/3d/editable_shape.h73
-rw-r--r--scene/3d/follow_camera.cpp778
-rw-r--r--scene/3d/follow_camera.h180
-rw-r--r--scene/3d/immediate_geometry.cpp52
-rw-r--r--scene/3d/immediate_geometry.h5
-rw-r--r--scene/3d/interpolated_camera.cpp10
-rw-r--r--scene/3d/light.cpp55
-rw-r--r--scene/3d/light.h8
-rw-r--r--scene/3d/mesh_instance.cpp21
-rw-r--r--scene/3d/navigation.cpp57
-rw-r--r--scene/3d/navigation.h8
-rw-r--r--scene/3d/navigation_mesh.cpp12
-rw-r--r--scene/3d/path.cpp720
-rw-r--r--scene/3d/physics_body.cpp88
-rw-r--r--scene/3d/physics_body.h14
-rw-r--r--scene/3d/physics_joint.cpp29
-rw-r--r--scene/3d/physics_joint.h5
-rw-r--r--scene/3d/proximity_group.cpp4
-rw-r--r--scene/3d/quad.cpp6
-rw-r--r--scene/3d/ray_cast.cpp68
-rw-r--r--scene/3d/ray_cast.h9
-rw-r--r--scene/3d/room_instance.cpp2
-rw-r--r--scene/3d/skeleton.cpp20
-rw-r--r--scene/3d/skeleton.h2
-rw-r--r--scene/3d/spatial.cpp24
-rw-r--r--scene/3d/spatial.h2
-rw-r--r--scene/3d/spatial_sample_player.cpp1
-rw-r--r--scene/3d/spatial_stream_player.cpp4
-rw-r--r--scene/3d/sprite_3d.cpp14
-rw-r--r--scene/3d/vehicle_body.cpp17
-rw-r--r--scene/3d/visibility_notifier.cpp14
-rw-r--r--scene/3d/visual_instance.cpp22
-rw-r--r--scene/3d/visual_instance.h1
-rw-r--r--scene/SCsub2
-rw-r--r--scene/animation/animation_cache.cpp10
-rw-r--r--scene/animation/animation_cache.h2
-rw-r--r--scene/animation/animation_player.cpp37
-rw-r--r--scene/animation/animation_player.h5
-rw-r--r--scene/animation/animation_tree_player.cpp7
-rw-r--r--scene/animation/tween.cpp199
-rw-r--r--scene/animation/tween.h45
-rw-r--r--scene/audio/event_player.cpp16
-rw-r--r--scene/audio/sample_player.cpp1
-rw-r--r--scene/audio/sound_room_params.cpp10
-rw-r--r--scene/audio/stream_player.cpp12
-rw-r--r--scene/gui/base_button.cpp66
-rw-r--r--scene/gui/base_button.h20
-rw-r--r--scene/gui/box_container.cpp4
-rw-r--r--scene/gui/button_group.cpp5
-rw-r--r--scene/gui/container.cpp6
-rw-r--r--scene/gui/control.cpp178
-rw-r--r--scene/gui/dialogs.cpp4
-rw-r--r--scene/gui/empty_control.cpp59
-rw-r--r--scene/gui/empty_control.h48
-rw-r--r--scene/gui/graph_edit.cpp586
-rw-r--r--scene/gui/graph_edit.h100
-rw-r--r--scene/gui/graph_node.cpp583
-rw-r--r--scene/gui/graph_node.h101
-rw-r--r--scene/gui/grid_container.cpp1
-rw-r--r--scene/gui/label.cpp7
-rw-r--r--scene/gui/line_edit.cpp2
-rw-r--r--scene/gui/menu_button.cpp1
-rw-r--r--scene/gui/option_button.cpp2
-rw-r--r--scene/gui/popup.cpp15
-rw-r--r--scene/gui/popup_menu.cpp21
-rw-r--r--scene/gui/popup_menu.h4
-rw-r--r--scene/gui/range.cpp4
-rw-r--r--scene/gui/reference_frame.cpp4
-rw-r--r--scene/gui/scroll_bar.cpp16
-rw-r--r--scene/gui/scroll_container.cpp2
-rw-r--r--scene/gui/spin_box.cpp2
-rw-r--r--scene/gui/tab_container.cpp33
-rw-r--r--scene/gui/tab_container.h2
-rw-r--r--scene/gui/text_edit.cpp2404
-rw-r--r--scene/gui/text_edit.h23
-rw-r--r--scene/gui/texture_button.cpp81
-rw-r--r--scene/gui/texture_button.h7
-rw-r--r--scene/gui/tree.cpp20
-rw-r--r--scene/gui/video_player.cpp39
-rw-r--r--scene/gui/video_player.h2
-rw-r--r--scene/io/resource_format_image.cpp47
-rw-r--r--scene/io/scene_format_object.cpp851
-rw-r--r--scene/io/scene_format_object.h128
-rw-r--r--scene/io/scene_format_script.cpp65
-rw-r--r--scene/io/scene_format_script.h45
-rw-r--r--scene/io/scene_loader.cpp161
-rw-r--r--scene/io/scene_loader.h90
-rw-r--r--scene/io/scene_saver.cpp94
-rw-r--r--scene/io/scene_saver.h80
-rw-r--r--scene/main/canvas_layer.cpp6
-rw-r--r--scene/main/node.cpp200
-rw-r--r--scene/main/node.h22
-rw-r--r--scene/main/scene_main_loop.cpp152
-rw-r--r--scene/main/scene_main_loop.h24
-rw-r--r--scene/main/timer.cpp7
-rw-r--r--scene/main/viewport.cpp110
-rw-r--r--scene/main/viewport.h9
-rw-r--r--scene/register_scene_types.cpp98
-rw-r--r--scene/resources/SCsub1
-rw-r--r--scene/resources/animation.cpp287
-rw-r--r--scene/resources/animation.h5
-rw-r--r--scene/resources/audio_stream_resampled.cpp30
-rw-r--r--scene/resources/audio_stream_resampled.h4
-rw-r--r--scene/resources/baked_light.cpp94
-rw-r--r--scene/resources/baked_light.h25
-rw-r--r--scene/resources/circle_shape_2d.cpp4
-rw-r--r--scene/resources/curve.cpp6
-rw-r--r--scene/resources/default_theme/default_theme.cpp19
-rw-r--r--scene/resources/default_theme/graph_node.pngbin0 -> 770 bytes
-rw-r--r--scene/resources/default_theme/graph_node_close.pngbin0 -> 243 bytes
-rw-r--r--scene/resources/default_theme/graph_port.pngbin0 -> 509 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h15
-rw-r--r--scene/resources/image_path_finder.cpp427
-rw-r--r--scene/resources/image_path_finder.h84
-rw-r--r--scene/resources/material.cpp177
-rw-r--r--scene/resources/material.h70
-rw-r--r--scene/resources/mesh.cpp246
-rw-r--r--scene/resources/mesh.h3
-rw-r--r--scene/resources/mikktspace.c1890
-rw-r--r--scene/resources/mikktspace.h145
-rw-r--r--scene/resources/packed_scene.cpp50
-rw-r--r--scene/resources/polygon_path_finder.cpp4
-rw-r--r--scene/resources/scene_preloader.cpp853
-rw-r--r--scene/resources/shader.cpp61
-rw-r--r--scene/resources/shader.h44
-rw-r--r--scene/resources/shader_graph.cpp2532
-rw-r--r--scene/resources/shader_graph.h413
-rw-r--r--scene/resources/shape_2d.cpp2
-rw-r--r--scene/resources/surface_tool.cpp206
-rw-r--r--scene/resources/surface_tool.h10
-rw-r--r--scene/resources/texture.cpp4
-rw-r--r--scene/resources/texture.h2
-rw-r--r--scene/resources/video_stream.cpp1
-rw-r--r--scene/resources/video_stream.h6
-rw-r--r--scene/resources/world_2d.cpp4
-rw-r--r--scene/scene_binds.cpp55
-rw-r--r--scene/scene_binds.h62
-rw-r--r--scene/scene_string_names.cpp18
-rw-r--r--scene/scene_string_names.h17
-rw-r--r--servers/SCsub2
-rw-r--r--servers/audio/audio_server_sw.cpp8
-rw-r--r--servers/audio/audio_server_sw.h5
-rw-r--r--servers/audio_server.h1
-rw-r--r--servers/physics/area_pair_sw.cpp3
-rw-r--r--servers/physics/area_sw.cpp6
-rw-r--r--servers/physics/area_sw.h3
-rw-r--r--servers/physics/body_pair_sw.cpp72
-rw-r--r--servers/physics/body_pair_sw.h1
-rw-r--r--servers/physics/body_sw.cpp16
-rw-r--r--servers/physics/body_sw.h3
-rw-r--r--servers/physics/collision_object_sw.cpp1
-rw-r--r--servers/physics/collision_object_sw.h11
-rw-r--r--servers/physics/collision_solver_sw.cpp44
-rw-r--r--servers/physics/collision_solver_sw.h1
-rw-r--r--servers/physics/constraint_sw.h6
-rw-r--r--servers/physics/physics_server_sw.cpp40
-rw-r--r--servers/physics/physics_server_sw.h6
-rw-r--r--servers/physics/space_sw.cpp5
-rw-r--r--servers/physics/step_sw.cpp39
-rw-r--r--servers/physics_2d/area_2d_sw.cpp10
-rw-r--r--servers/physics_2d/area_2d_sw.h10
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp2
-rw-r--r--servers/physics_2d/body_2d_sw.cpp84
-rw-r--r--servers/physics_2d/body_2d_sw.h29
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp9
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp8
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h15
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp1
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp62
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h13
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp33
-rw-r--r--servers/physics_2d/shape_2d_sw.h33
-rw-r--r--servers/physics_2d/space_2d_sw.cpp92
-rw-r--r--servers/physics_2d/space_2d_sw.h3
-rw-r--r--servers/physics_2d_server.cpp38
-rw-r--r--servers/physics_2d_server.h25
-rw-r--r--servers/physics_server.cpp18
-rw-r--r--servers/physics_server.h6
-rw-r--r--servers/register_server_types.cpp1
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.cpp13
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp2
-rw-r--r--servers/visual/rasterizer.cpp25
-rw-r--r--servers/visual/rasterizer.h299
-rw-r--r--servers/visual/rasterizer_dummy.cpp40
-rw-r--r--servers/visual/rasterizer_dummy.h19
-rw-r--r--servers/visual/shader_graph.h3
-rw-r--r--servers/visual/shader_language.cpp148
-rw-r--r--servers/visual/shader_language.h9
-rw-r--r--servers/visual/visual_server_raster.cpp1176
-rw-r--r--servers/visual/visual_server_raster.h237
-rw-r--r--servers/visual/visual_server_wrap_mt.h36
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h59
-rw-r--r--tools/SCsub19
-rw-r--r--tools/collada/collada.cpp50
-rw-r--r--tools/collada/collada.h26
-rw-r--r--tools/doc/doc_data.cpp14
-rw-r--r--tools/docdump/class_list.xml2
-rw-r--r--tools/docdump/makemd.py2
-rw-r--r--tools/editor/animation_editor.cpp104
-rw-r--r--tools/editor/animation_editor.h10
-rw-r--r--tools/editor/call_dialog.cpp4
-rw-r--r--tools/editor/code_editor.cpp28
-rw-r--r--tools/editor/code_editor.h4
-rw-r--r--tools/editor/console.cpp4
-rw-r--r--tools/editor/create_dialog.cpp2
-rw-r--r--tools/editor/editor_data.cpp4
-rw-r--r--tools/editor/editor_dir_dialog.cpp2
-rw-r--r--tools/editor/editor_file_system.cpp35
-rw-r--r--tools/editor/editor_file_system.h3
-rw-r--r--tools/editor/editor_help.cpp8
-rw-r--r--tools/editor/editor_import_export.cpp14
-rw-r--r--tools/editor/editor_log.cpp6
-rw-r--r--tools/editor/editor_log.h4
-rw-r--r--tools/editor/editor_node.cpp235
-rw-r--r--tools/editor/editor_node.h7
-rw-r--r--tools/editor/editor_plugin.cpp6
-rw-r--r--tools/editor/editor_plugin.h3
-rw-r--r--tools/editor/editor_run_native.cpp2
-rw-r--r--tools/editor/editor_settings.cpp13
-rw-r--r--tools/editor/editor_shape_gizmos.cpp468
-rw-r--r--tools/editor/editor_shape_gizmos.h60
-rw-r--r--tools/editor/groups_editor.cpp2
-rw-r--r--tools/editor/icons/icon_baked_light.pngbin0 -> 419 bytes
-rw-r--r--tools/editor/icons/icon_baked_light_instance.pngbin0 -> 380 bytes
-rw-r--r--tools/editor/icons/icon_canvas_item_shader.pngbin0 -> 568 bytes
-rw-r--r--tools/editor/icons/icon_canvas_item_shader_graph.pngbin0 -> 575 bytes
-rw-r--r--tools/editor/icons/icon_collision_polygon.pngbin0 -> 419 bytes
-rw-r--r--tools/editor/icons/icon_graph_comment.pngbin0 -> 310 bytes
-rw-r--r--tools/editor/icons/icon_graph_cube_uniform.pngbin0 -> 652 bytes
-rw-r--r--tools/editor/icons/icon_graph_input.pngbin0 -> 585 bytes
-rw-r--r--tools/editor/icons/icon_graph_rgb.pngbin0 -> 174 bytes
-rw-r--r--tools/editor/icons/icon_graph_rgb_op.pngbin0 -> 280 bytes
-rw-r--r--tools/editor/icons/icon_graph_rgb_uniform.pngbin0 -> 419 bytes
-rw-r--r--tools/editor/icons/icon_graph_scalar.pngbin0 -> 328 bytes
-rw-r--r--tools/editor/icons/icon_graph_scalar_interp.pngbin0 -> 352 bytes
-rw-r--r--tools/editor/icons/icon_graph_scalar_op.pngbin0 -> 238 bytes
-rw-r--r--tools/editor/icons/icon_graph_scalar_uniform.pngbin0 -> 392 bytes
-rw-r--r--tools/editor/icons/icon_graph_scalars_to_vec.pngbin0 -> 300 bytes
-rw-r--r--tools/editor/icons/icon_graph_texscreen.pngbin0 -> 578 bytes
-rw-r--r--tools/editor/icons/icon_graph_texture_uniform.pngbin0 -> 358 bytes
-rw-r--r--tools/editor/icons/icon_graph_time.pngbin0 -> 678 bytes
-rw-r--r--tools/editor/icons/icon_graph_vec_dp.pngbin0 -> 279 bytes
-rw-r--r--tools/editor/icons/icon_graph_vec_interp.pngbin0 -> 332 bytes
-rw-r--r--tools/editor/icons/icon_graph_vec_length.pngbin0 -> 303 bytes
-rw-r--r--tools/editor/icons/icon_graph_vec_op.pngbin0 -> 256 bytes
-rw-r--r--tools/editor/icons/icon_graph_vec_scalar_op.pngbin0 -> 267 bytes
-rw-r--r--tools/editor/icons/icon_graph_vec_to_scalars.pngbin0 -> 306 bytes
-rw-r--r--tools/editor/icons/icon_graph_vecs_to_xform.pngbin0 -> 288 bytes
-rw-r--r--tools/editor/icons/icon_graph_vector.pngbin0 -> 480 bytes
-rw-r--r--tools/editor/icons/icon_graph_vector_uniform.pngbin0 -> 531 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform.pngbin0 -> 262 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform_mult.pngbin0 -> 311 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform_scalar_func.pngbin0 -> 378 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform_to_vecs.pngbin0 -> 272 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform_uniform.pngbin0 -> 346 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform_vec_func.pngbin0 -> 389 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform_vec_imult.pngbin0 -> 430 bytes
-rw-r--r--tools/editor/icons/icon_graph_xform_vec_mult.pngbin0 -> 422 bytes
-rw-r--r--tools/editor/icons/icon_immediate_geometry.pngbin0 -> 363 bytes
-rw-r--r--tools/editor/icons/icon_kinematic_body.pngbin0 -> 474 bytes
-rw-r--r--tools/editor/icons/icon_kinematic_body_2d.pngbin0 -> 475 bytes
-rw-r--r--tools/editor/icons/icon_material_shader.pngbin0 -> 844 bytes
-rw-r--r--tools/editor/icons/icon_material_shader_graph.pngbin0 -> 949 bytes
-rw-r--r--tools/editor/icons/icon_navigation.pngbin0 -> 598 bytes
-rw-r--r--tools/editor/icons/icon_navigation_mesh_instance.pngbin0 -> 455 bytes
-rw-r--r--tools/editor/icons/icon_panels_2_alt.pngbin0 -> 156 bytes
-rw-r--r--tools/editor/icons/icon_panels_3_alt.pngbin0 -> 167 bytes
-rw-r--r--tools/editor/icons/icon_particle_attractor_2d.pngbin0 -> 574 bytes
-rw-r--r--tools/editor/icons/icon_pin_joint.pngbin0 -> 334 bytes
-rw-r--r--tools/editor/icons/icon_polygon_2d.pngbin0 -> 405 bytes
-rw-r--r--tools/editor/icons/icon_ray_cast.pngbin0 -> 214 bytes
-rw-r--r--tools/editor/icons/icon_slider_joint.pngbin0 -> 283 bytes
-rw-r--r--tools/editor/icons/icon_touch_screen_button.pngbin0 -> 434 bytes
-rw-r--r--tools/editor/icons/icon_vehicle_body.pngbin0 -> 443 bytes
-rw-r--r--tools/editor/icons/icon_vehicle_wheel.pngbin0 -> 528 bytes
-rw-r--r--tools/editor/icons/icon_y_sort.pngbin0 -> 392 bytes
-rw-r--r--tools/editor/import_settings.cpp2
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.cpp18
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp119
-rw-r--r--tools/editor/io_plugins/editor_import_collada.h2
-rw-r--r--tools/editor/io_plugins/editor_mesh_import_plugin.cpp4
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.cpp2
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.cpp885
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.h34
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp44
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.h5
-rw-r--r--tools/editor/io_plugins/editor_translation_import_plugin.cpp2
-rw-r--r--tools/editor/output_strings.cpp2
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.cpp8
-rw-r--r--tools/editor/plugins/animation_tree_editor_plugin.cpp6
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp782
-rw-r--r--tools/editor/plugins/baked_light_baker.h49
-rw-r--r--tools/editor/plugins/baked_light_baker_cmpxchg.cpp85
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp20
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h5
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp31
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.h7
-rw-r--r--tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp9
-rw-r--r--tools/editor/plugins/collision_polygon_editor_plugin.cpp4
-rw-r--r--tools/editor/plugins/item_list_editor_plugin.cpp3
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp282
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.h74
-rw-r--r--tools/editor/plugins/particles_2d_editor_plugin.cpp340
-rw-r--r--tools/editor/plugins/particles_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/path_2d_editor_plugin.cpp4
-rw-r--r--tools/editor/plugins/path_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/polygon_2d_editor_plugin.cpp9
-rw-r--r--tools/editor/plugins/resource_preloader_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/sample_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.cpp6
-rw-r--r--tools/editor/plugins/sample_player_editor_plugin.cpp7
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp296
-rw-r--r--tools/editor/plugins/script_editor_plugin.h10
-rw-r--r--tools/editor/plugins/shader_editor_plugin.cpp78
-rw-r--r--tools/editor/plugins/shader_editor_plugin.h6
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.cpp2088
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.h174
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp425
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.h53
-rw-r--r--tools/editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/stream_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.cpp198
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.h13
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.cpp5
-rw-r--r--tools/editor/progress_dialog.cpp7
-rw-r--r--tools/editor/project_export.cpp18
-rw-r--r--tools/editor/project_export.h2
-rw-r--r--tools/editor/project_manager.cpp22
-rw-r--r--tools/editor/project_settings.cpp6
-rw-r--r--tools/editor/property_editor.cpp93
-rw-r--r--tools/editor/property_editor.h6
-rw-r--r--tools/editor/quick_open.cpp2
-rw-r--r--tools/editor/reparent_dialog.cpp2
-rw-r--r--tools/editor/resources_dock.cpp69
-rw-r--r--tools/editor/scene_tree_dock.cpp57
-rw-r--r--tools/editor/scene_tree_editor.cpp26
-rw-r--r--tools/editor/scenes_dock.cpp13
-rw-r--r--tools/editor/script_editor_debugger.cpp6
-rw-r--r--tools/editor/settings_config_dialog.cpp2
-rw-r--r--tools/editor/spatial_editor_gizmos.cpp206
-rw-r--r--tools/editor/spatial_editor_gizmos.h15
-rw-r--r--tools/export/blender25/godot_export_manager.py439
-rw-r--r--tools/export/blender25/install.txt16
-rw-r--r--tools/export/blender25/io_scene_dae/__init__.py32
-rw-r--r--tools/export/blender25/io_scene_dae/export_dae.py713
-rw-r--r--version.py3
678 files changed, 35315 insertions, 28199 deletions
diff --git a/.gitignore b/.gitignore
index 45bf531311..4aee83c13f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ 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
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/README.md b/README.md
index dba980bba9..3456290f74 100644
--- a/README.md
+++ b/README.md
@@ -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 de7256f6bc..b9f2b7e2c4 100644
--- a/SConstruct
+++ b/SConstruct
@@ -6,16 +6,6 @@ import os.path
import glob
import sys
import methods
-import multiprocessing
-
-# Enable aggresive compile mode if building on a multi core box
-# only is we have not set the number of jobs already or we do
-# not want it
-if ARGUMENTS.get('spawn_jobs', 'no') == 'yes' and \
- int(GetOption('num_jobs')) <= 1:
- NUM_JOBS = multiprocessing.cpu_count()
- if NUM_JOBS > 1:
- SetOption('num_jobs', NUM_JOBS+1)
methods.update_version()
@@ -58,8 +48,7 @@ for x in glob.glob("platform/*"):
module_list=methods.detect_modules()
-print "Detected Platforms: "+str(platform_list)
-print("Detected Modules: "+str(module_list))
+#print "Detected Platforms: "+str(platform_list)
methods.save_active_platforms(active_platforms,active_platform_ids)
@@ -99,20 +88,17 @@ if profile:
customs.append(profile+".py")
opts=Variables(customs, ARGUMENTS)
-opts.Add('target', 'Compile Target (debug/profile/release).', "debug")
-opts.Add('platform','Platform: '+str(platform_list)+'(sfml).',"")
-opts.Add('python','Build Python Support: (yes/no)','no')
-opts.Add('squirrel','Build Squirrel Support: (yes/no)','no')
+opts.Add('target', 'Compile Target (debug/release_debug/release).', "debug")
+opts.Add('bits', 'Compile Target Bits (default/32/64).', "default")
+opts.Add('platform','Platform: '+str(platform_list)+'.',"")
+opts.Add('p','Platform (same as platform=).',"")
opts.Add('tools','Build Tools (Including Editor): (yes/no)','yes')
-opts.Add('lua','Build Lua Support: (yes/no)','no')
-opts.Add('rfd','Remote Filesystem Driver: (yes/no)','no')
opts.Add('gdscript','Build GDSCript support: (yes/no)','yes')
opts.Add('vorbis','Build Ogg Vorbis Support: (yes/no)','yes')
opts.Add('minizip','Build Minizip Archive Support: (yes/no)','yes')
-opts.Add('opengl', 'Build OpenGL Support: (yes/no)', 'yes')
-opts.Add('game', 'Game (custom) Code Directory', "")
-opts.Add('squish','Squish BC Texture Compression (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')
@@ -124,15 +110,12 @@ opts.Add('pvr','PVR (PowerVR) Texture loader 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')
-opts.Add('default_gui_theme','Default GUI theme (yes/no)','yes')
opts.Add("CXX", "Compiler");
-opts.Add("nedmalloc", "Add nedmalloc support", 'yes');
opts.Add("CCFLAGS", "Custom flags for the C++ compiler");
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('old_scenes', 'Compatibility with old-style scenes', "yes")
# add platform specific options
@@ -150,9 +133,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
-env_base.detect_python=True
+
+# configure ENV for platform
env_base.platform_exporters=platform_exporters
"""
@@ -170,17 +152,26 @@ if (env_base['target']=='debug'):
env_base.platforms = {}
-for p in platform_list:
+selected_platform =""
- if env_base['platform'] != "" and env_base['platform'] != p:
- continue
- sys.path.append("./platform/"+p)
+if env_base['platform'] != "":
+ selected_platform=env_base['platform']
+elif env_base['p'] != "":
+ selected_platform=env_base['p']
+ env_base["platform"]=selected_platform
+
+
+if selected_platform in platform_list:
+
+ sys.path.append("./platform/"+selected_platform)
import detect
if "create" in dir(detect):
env = detect.create(env_base)
else:
env = env_base.Clone()
+ env.extra_suffix=""
+
CCFLAGS = env.get('CCFLAGS', '')
env['CCFLAGS'] = ''
@@ -197,17 +188,49 @@ for p in platform_list:
env.Append(LINKFLAGS=string.split(str(LINKFLAGS)))
detect.configure(env)
- env['platform'] = p
- if not env.has_key('platform_libsuffix'):
- env['platform_libsuffix'] = env['LIBSUFFIX']
- sys.path.remove("./platform/"+p)
- sys.modules.pop('detect')
- flag_list = platform_flags[p]
+
+ flag_list = platform_flags[selected_platform]
for f in flag_list:
if not (f[0] in ARGUMENTS): # allow command line to override platform flags
env[f[0]] = f[1]
- print(f[0]+":"+f[1])
+
+ #env['platform_libsuffix'] = env['LIBSUFFIX']
+
+ suffix="."+selected_platform
+
+ if (env["target"]=="release"):
+ if (env["tools"]=="yes"):
+ print("Tools can only be built with targets 'debug' and 'release_debug'.")
+ sys.exit(255)
+ suffix+=".opt"
+
+ elif (env["target"]=="release_debug"):
+ if (env["tools"]=="yes"):
+ suffix+=".opt.tools"
+ else:
+ suffix+=".opt.debug"
+ else:
+ if (env["tools"]=="yes"):
+ suffix+=".tools"
+ else:
+ suffix+=".debug"
+
+ if (env["bits"]=="32"):
+ suffix+=".32"
+ elif (env["bits"]=="64"):
+ suffix+=".64"
+
+ suffix+=env.extra_suffix
+
+ env["PROGSUFFIX"]=suffix+env["PROGSUFFIX"]
+ env["OBJSUFFIX"]=suffix+env["OBJSUFFIX"]
+ env["LIBSUFFIX"]=suffix+env["LIBSUFFIX"]
+ env["SHLIBSUFFIX"]=suffix+env["SHLIBSUFFIX"]
+
+ sys.path.remove("./platform/"+selected_platform)
+ sys.modules.pop('detect')
+
env.module_list=[]
@@ -218,7 +241,7 @@ for p in platform_list:
sys.path.append(tmppath)
env.current_module=x
import config
- if (config.can_build(p)):
+ if (config.can_build(selected_platform)):
config.configure(env)
env.module_list.append(x)
sys.path.remove(tmppath)
@@ -232,11 +255,6 @@ for p in platform_list:
if (env['openssl']=="builtin"):
env.Append(CPPPATH=['#drivers/builtin_openssl2'])
-
- if (env["old_scenes"]=='yes'):
- env.Append(CPPFLAGS=['-DOLD_SCENE_FORMAT_ENABLED'])
- if (env["rfd"]=='yes'):
- env.Append(CPPFLAGS=['-DRFD_ENABLED'])
if (env["builtin_zlib"]=='yes'):
env.Append(CPPPATH=['#drivers/builtin_zlib/zlib'])
@@ -281,34 +299,6 @@ for p in platform_list:
if (env['xml']=='yes'):
env.Append(CPPFLAGS=['-DXML_ENABLED'])
- if (env['default_gui_theme']=='no'):
- env.Append(CPPFLAGS=['-DDEFAULT_THEME_DISABLED'])
-
- if (env["python"]=='yes'):
- detected=False;
- if (env.detect_python):
- print("Python 3.0 Prefix:");
- pycfg_exec="python3-config"
- errorval=os.system(pycfg_exec+" --prefix")
- prefix=""
- if (not errorval):
- #gah, why can't it get both at the same time like pkg-config, sdl-config, etc?
- env.ParseConfig(pycfg_exec+" --cflags")
- env.ParseConfig(pycfg_exec+" --libs")
- detected=True
-
- if (detected):
- env.Append(CPPFLAGS=['-DPYTHON_ENABLED'])
- #remove annoying warnings
- if ('-Wstrict-prototypes' in env["CCFLAGS"]):
- env["CCFLAGS"].remove('-Wstrict-prototypes');
- if ('-fwrapv' in env["CCFLAGS"]):
- env["CCFLAGS"].remove('-fwrapv');
- else:
- print("Python 3.0 not detected ("+pycfg_exec+") support disabled.");
-
- #if env['nedmalloc'] == 'yes':
- # env.Append(CPPFLAGS = ['-DNEDMALLOC_ENABLED'])
Export('env')
@@ -321,11 +311,15 @@ for p in platform_list:
SConscript("drivers/SCsub")
SConscript("bin/SCsub")
- if env['game']:
- SConscript(env['game']+'/SCsub')
-
SConscript("modules/SCsub")
SConscript("main/SCsub")
- SConscript("platform/"+p+"/SCsub"); # build selected platform
+ SConscript("platform/"+selected_platform+"/SCsub"); # build selected platform
+
+else:
+ print("No valid target platform selected.")
+ print("The following were detected:")
+ for x in platform_list:
+ print("\t"+x)
+ print("\nPlease run scons again with argument: platform=<string>")
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..17a6a4111c 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
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/core/SCsub b/core/SCsub
index 2b195fa750..d04041141c 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -60,7 +60,7 @@ SConscript('math/SCsub');
SConscript('io/SCsub');
SConscript('bind/SCsub');
-lib = env.Library("core",env.core_sources, LIBSUFFIX=env['platform_libsuffix'])
+lib = env.Library("core",env.core_sources)
env.Prepend(LIBS=[lib])
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 570ed33a5a..0c5d21b4f6 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);
@@ -577,9 +577,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 +597,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 {
@@ -628,7 +642,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 +682,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,6 +696,7 @@ 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("get_frames_per_second"),&_OS::get_frames_per_second);
@@ -718,6 +735,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 );
}
@@ -856,6 +881,42 @@ Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2>& p_polygon) {
return Geometry::triangulate_polygon(p_polygon);
}
+Dictionary _Geometry::make_atlas(const Vector<Size2>& p_rects) {
+
+ Dictionary ret;
+
+ Vector<Size2i> rects;
+ for (int i=0; i<p_rects.size(); i++) {
+
+ rects.push_back(p_rects[i]);
+ };
+
+ Vector<Point2i> result;
+ Size2i size;
+
+ Geometry::make_atlas(rects, result, size);
+
+ Size2 r_size = size;
+ Vector<Point2> r_result;
+ for (int i=0; i<result.size(); i++) {
+
+ r_result.push_back(result[i]);
+ };
+
+
+ ret["points"] = r_result;
+ ret["size"] = r_size;
+
+ return ret;
+};
+
+
+int _Geometry::get_uv84_normal_bit(const Vector3& p_vector) {
+
+ return Geometry::get_uv84_normal_bit(p_vector);
+}
+
+
void _Geometry::_bind_methods() {
@@ -870,6 +931,8 @@ void _Geometry::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","point","s1","s2"),&_Geometry::get_closest_point_to_segment);
+ ObjectTypeDB::bind_method(_MD("get_uv84_normal_bit","normal"),&_Geometry::get_uv84_normal_bit);
+
ObjectTypeDB::bind_method(_MD("ray_intersects_triangle","from","dir","a","b","c"),&_Geometry::ray_intersects_triangle);
ObjectTypeDB::bind_method(_MD("segment_intersects_triangle","from","to","a","b","c"),&_Geometry::segment_intersects_triangle);
ObjectTypeDB::bind_method(_MD("segment_intersects_sphere","from","to","spos","sradius"),&_Geometry::segment_intersects_sphere);
@@ -878,6 +941,7 @@ void _Geometry::_bind_methods() {
ObjectTypeDB::bind_method(_MD("triangulate_polygon","polygon"),&_Geometry::triangulate_polygon);
+ ObjectTypeDB::bind_method(_MD("make_atlas","sizes"),&_Geometry::make_atlas);
}
@@ -1057,6 +1121,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 0ef70e4b13..12a4ae86eb 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,7 @@ 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);
+ 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 +154,8 @@ public:
bool has_touchscreen_ui_hint() const;
+ bool is_debug_build() const;
+
String get_unique_ID() const;
/*
@@ -199,6 +201,20 @@ 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);
@@ -209,6 +225,9 @@ public:
_OS();
};
+VARIANT_ENUM_CAST(_OS::SystemDir);
+
+
class _Geometry : public Object {
OBJ_TYPE(_Geometry, Object);
@@ -233,9 +252,12 @@ public:
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);
real_t segment_intersects_circle(const Vector2& p_from, const Vector2& p_to, const Vector2& p_circle_pos, real_t p_circle_radius);
+ int get_uv84_normal_bit(const Vector3& p_vector);
Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon);
+ Dictionary make_atlas(const Vector<Size2>& p_rects);
+
_Geometry();
};
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/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 d9ba6c1594..17ee569b6b 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) {
@@ -1200,6 +1201,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)
@@ -1998,6 +2007,26 @@ void Image::set_compress_bc_func(void (*p_compress_func)(Image *)) {
+void Image::normalmap_to_xy() {
+
+ convert(Image::FORMAT_RGBA);
+
+ {
+ int len = data.size()/4;
+ DVector<uint8_t>::Write wp = data.write();
+ unsigned char *data_ptr=wp.ptr();
+
+ for(int i=0;i<len;i++) {
+
+ data_ptr[(i<<2)+3]=data_ptr[(i<<2)+0]; //x to w
+ data_ptr[(i<<2)+0]=data_ptr[(i<<2)+1]; //y to xz
+ data_ptr[(i<<2)+2]=data_ptr[(i<<2)+1];
+ }
+ }
+
+ convert(Image::FORMAT_GRAYSCALE_ALPHA);
+}
+
void Image::srgb_to_linear() {
if (data.size()==0)
diff --git a/core/image.h b/core/image.h
index 7a6ee1e4b0..f4c96703b9 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
@@ -216,6 +220,14 @@ public:
* Convert the image to another format, as close as it can be done.
*/
void convert( Format p_new_format );
+
+ Image converted(int p_new_format) {
+ ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image());
+
+ Image ret = *this;
+ ret.convert((Format)p_new_format);
+ return ret;
+ };
/**
* Get the current image format.
@@ -270,6 +282,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
@@ -325,6 +338,7 @@ public:
void fix_alpha_edges();
void premultiply_alpha();
void srgb_to_linear();
+ void normalmap_to_xy();
void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);
diff --git a/core/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/http_client.cpp b/core/io/http_client.cpp
index 60a200af12..faead675d4 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;
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/object_format_binary.cpp b/core/io/object_format_binary.cpp
deleted file mode 100644
index c031f6e82b..0000000000
--- a/core/io/object_format_binary.cpp
+++ /dev/null
@@ -1,1491 +0,0 @@
-/*************************************************************************/
-/* object_format_binary.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 "object_format_binary.h"
-#include "resource.h"
-#include "io/resource_loader.h"
-#include "print_string.h"
-#include "object_type_db.h"
-#include "globals.h"
-#include "os/os.h"
-#include "version.h"
-
-
-#define print_bl(m_what)
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-
-enum {
-
- SECTION_RESOURCE=0,
- SECTION_OBJECT=1,
- SECTION_META_OBJECT=2,
- SECTION_PROPERTY=3,
- SECTION_END=4,
-
- //numbering must be different from variant, in case new variant types are added (variant must be always contiguous for jumptable optimization)
- VARIANT_NIL=1,
- VARIANT_BOOL=2,
- VARIANT_INT=3,
- VARIANT_REAL=4,
- VARIANT_STRING=5,
- VARIANT_VECTOR2=10,
- VARIANT_RECT2=11,
- VARIANT_VECTOR3=12,
- VARIANT_PLANE=13,
- VARIANT_QUAT=14,
- VARIANT_AABB=15,
- VARIANT_MATRIX3=16,
- VARIANT_TRANSFORM=17,
- VARIANT_MATRIX32=18,
- VARIANT_COLOR=20,
- VARIANT_IMAGE=21,
- VARIANT_NODE_PATH=22,
- VARIANT_RID=23,
- VARIANT_OBJECT=24,
- VARIANT_INPUT_EVENT=25,
- VARIANT_DICTIONARY=26,
- VARIANT_ARRAY=30,
- VARIANT_RAW_ARRAY=31,
- VARIANT_INT_ARRAY=32,
- VARIANT_REAL_ARRAY=33,
- VARIANT_STRING_ARRAY=34,
- VARIANT_VECTOR3_ARRAY=35,
- VARIANT_COLOR_ARRAY=36,
- VARIANT_VECTOR2_ARRAY=37,
-
- IMAGE_ENCODING_EMPTY=0,
- IMAGE_ENCODING_RAW=1,
- IMAGE_ENCODING_PNG=2, //not yet
- IMAGE_ENCODING_JPG=3,
-
- IMAGE_FORMAT_GRAYSCALE=0,
- IMAGE_FORMAT_INTENSITY=1,
- IMAGE_FORMAT_GRAYSCALE_ALPHA=2,
- IMAGE_FORMAT_RGB=3,
- IMAGE_FORMAT_RGBA=4,
- IMAGE_FORMAT_INDEXED=5,
- IMAGE_FORMAT_INDEXED_ALPHA=6,
- IMAGE_FORMAT_BC1=7,
- IMAGE_FORMAT_BC2=8,
- IMAGE_FORMAT_BC3=9,
- IMAGE_FORMAT_BC4=10,
- IMAGE_FORMAT_BC5=11,
- IMAGE_FORMAT_CUSTOM=12,
-
- OBJECT_EMPTY=0,
- OBJECT_EXTERNAL_RESOURCE=1,
- OBJECT_INTERNAL_RESOURCE=2,
-
-
-};
-
-
-void ObjectFormatSaverBinary::_pad_buffer(int p_bytes) {
-
- int extra = 4-(p_bytes%4);
- if (extra<4) {
- for(int i=0;i<extra;i++)
- f->store_8(0); //pad to 32
- }
-
-}
-
-
-void ObjectFormatSaverBinary::write_property(int p_idx,const Variant& p_property) {
-
- f->store_32(SECTION_PROPERTY);
- f->store_32(p_idx);
-
- switch(p_property.get_type()) {
-
- case Variant::NIL: {
-
- f->store_32(VARIANT_NIL);
- // don't store anything
- } break;
- case Variant::BOOL: {
-
- f->store_32(VARIANT_BOOL);
- bool val=p_property;
- f->store_32(val);
- } break;
- case Variant::INT: {
-
- f->store_32(VARIANT_INT);
- int val=p_property;
- f->store_32(val);
- } break;
- case Variant::REAL: {
-
- f->store_32(VARIANT_REAL);
- real_t val=p_property;
- f->store_real(val);
-
- } break;
- case Variant::STRING: {
-
- f->store_32(VARIANT_STRING);
- String val=p_property;
- save_unicode_string(val);
-
- } break;
- case Variant::VECTOR2: {
-
- f->store_32(VARIANT_VECTOR2);
- Vector2 val=p_property;
- f->store_real(val.x);
- f->store_real(val.y);
-
- } break;
- case Variant::RECT2: {
-
- f->store_32(VARIANT_RECT2);
- Rect2 val=p_property;
- f->store_real(val.pos.x);
- f->store_real(val.pos.y);
- f->store_real(val.size.x);
- f->store_real(val.size.y);
-
- } break;
- case Variant::VECTOR3: {
-
- f->store_32(VARIANT_VECTOR3);
- Vector3 val=p_property;
- f->store_real(val.x);
- f->store_real(val.y);
- f->store_real(val.z);
-
- } break;
- case Variant::PLANE: {
-
- f->store_32(VARIANT_PLANE);
- Plane val=p_property;
- f->store_real(val.normal.x);
- f->store_real(val.normal.y);
- f->store_real(val.normal.z);
- f->store_real(val.d);
-
- } break;
- case Variant::QUAT: {
-
- f->store_32(VARIANT_QUAT);
- Quat val=p_property;
- f->store_real(val.x);
- f->store_real(val.y);
- f->store_real(val.z);
- f->store_real(val.w);
-
- } break;
- case Variant::_AABB: {
-
- f->store_32(VARIANT_AABB);
- AABB val=p_property;
- f->store_real(val.pos.x);
- f->store_real(val.pos.y);
- f->store_real(val.pos.z);
- f->store_real(val.size.x);
- f->store_real(val.size.y);
- f->store_real(val.size.z);
-
- } break;
- case Variant::MATRIX32: {
-
- f->store_32(VARIANT_MATRIX32);
- Matrix32 val=p_property;
- f->store_real(val.elements[0].x);
- f->store_real(val.elements[0].y);
- f->store_real(val.elements[1].x);
- f->store_real(val.elements[1].y);
- f->store_real(val.elements[2].x);
- f->store_real(val.elements[2].y);
-
- } break;
- case Variant::MATRIX3: {
-
- f->store_32(VARIANT_MATRIX3);
- Matrix3 val=p_property;
- f->store_real(val.elements[0].x);
- f->store_real(val.elements[0].y);
- f->store_real(val.elements[0].z);
- f->store_real(val.elements[1].x);
- f->store_real(val.elements[1].y);
- f->store_real(val.elements[1].z);
- f->store_real(val.elements[2].x);
- f->store_real(val.elements[2].y);
- f->store_real(val.elements[2].z);
-
- } break;
- case Variant::TRANSFORM: {
-
- f->store_32(VARIANT_TRANSFORM);
- Transform val=p_property;
- f->store_real(val.basis.elements[0].x);
- f->store_real(val.basis.elements[0].y);
- f->store_real(val.basis.elements[0].z);
- f->store_real(val.basis.elements[1].x);
- f->store_real(val.basis.elements[1].y);
- f->store_real(val.basis.elements[1].z);
- f->store_real(val.basis.elements[2].x);
- f->store_real(val.basis.elements[2].y);
- f->store_real(val.basis.elements[2].z);
- f->store_real(val.origin.x);
- f->store_real(val.origin.y);
- f->store_real(val.origin.z);
-
- } break;
- case Variant::COLOR: {
-
- f->store_32(VARIANT_COLOR);
- Color val=p_property;
- f->store_real(val.r);
- f->store_real(val.g);
- f->store_real(val.b);
- f->store_real(val.a);
-
- } break;
- case Variant::IMAGE: {
-
- f->store_32(VARIANT_IMAGE);
- Image val =p_property;
- if (val.empty()) {
- f->store_32(IMAGE_ENCODING_EMPTY);
- break;
- }
- f->store_32(IMAGE_ENCODING_RAW); //raw encoding
- f->store_32(val.get_width());
- f->store_32(val.get_height());
- f->store_32(val.get_mipmaps());
- switch(val.get_format()) {
-
- case Image::FORMAT_GRAYSCALE: f->store_32(IMAGE_FORMAT_GRAYSCALE ); break; ///< one byte per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255
- case Image::FORMAT_INTENSITY: f->store_32(IMAGE_FORMAT_INTENSITY ); break; ///< one byte per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255
- case Image::FORMAT_GRAYSCALE_ALPHA: f->store_32(IMAGE_FORMAT_GRAYSCALE_ALPHA ); break; ///< two bytes per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255. alpha 0-255
- case Image::FORMAT_RGB: f->store_32(IMAGE_FORMAT_RGB ); break; ///< one byte R: f->store_32(IMAGE_FORMAT_ ); break; one byte G: f->store_32(IMAGE_FORMAT_ ); break; one byte B
- case Image::FORMAT_RGBA: f->store_32(IMAGE_FORMAT_RGBA ); break; ///< one byte R: f->store_32(IMAGE_FORMAT_ ); break; one byte G: f->store_32(IMAGE_FORMAT_ ); break; one byte B: f->store_32(IMAGE_FORMAT_ ); break; one byte A
- case Image::FORMAT_INDEXED: f->store_32(IMAGE_FORMAT_INDEXED ); break; ///< index byte 0-256: f->store_32(IMAGE_FORMAT_ ); break; and after image end: f->store_32(IMAGE_FORMAT_ ); break; 256*3 bytes of palette
- case Image::FORMAT_INDEXED_ALPHA: f->store_32(IMAGE_FORMAT_INDEXED_ALPHA ); break; ///< index byte 0-256: f->store_32(IMAGE_FORMAT_ ); break; and after image end: f->store_32(IMAGE_FORMAT_ ); break; 256*4 bytes of palette (alpha)
- case Image::FORMAT_BC1: f->store_32(IMAGE_FORMAT_BC1 ); break; // DXT1
- case Image::FORMAT_BC2: f->store_32(IMAGE_FORMAT_BC2 ); break; // DXT3
- case Image::FORMAT_BC3: f->store_32(IMAGE_FORMAT_BC3 ); break; // DXT5
- case Image::FORMAT_BC4: f->store_32(IMAGE_FORMAT_BC4 ); break; // ATI1
- case Image::FORMAT_BC5: f->store_32(IMAGE_FORMAT_BC5 ); break; // ATI2
- case Image::FORMAT_CUSTOM: f->store_32(IMAGE_FORMAT_CUSTOM ); break;
- default: {}
-
- }
-
- int dlen = val.get_data().size();
- f->store_32(dlen);
- DVector<uint8_t>::Read r = val.get_data().read();
- f->store_buffer(r.ptr(),dlen);
- _pad_buffer(dlen);
-
- } break;
- case Variant::NODE_PATH: {
- f->store_32(VARIANT_NODE_PATH);
- save_unicode_string(p_property);
- } break;
- case Variant::_RID: {
-
- f->store_32(VARIANT_RID);
- WARN_PRINT("Can't save RIDs");
- RID val = p_property;
- f->store_32(val.get_id());
- } break;
- case Variant::OBJECT: {
-
- f->store_32(VARIANT_OBJECT);
- RES res = p_property;
- if (res.is_null()) {
- f->store_32(OBJECT_EMPTY);
- return; // don't save it
- }
-
- if (res->get_path().length() && res->get_path().find("::")==-1) {
- f->store_32(OBJECT_EXTERNAL_RESOURCE);
- save_unicode_string(res->get_type());
- String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
- save_unicode_string(path);
- } else {
-
- if (!resource_map.has(res)) {
- f->store_32(OBJECT_EMPTY);
- ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
- ERR_FAIL();
- }
-
- f->store_32(OBJECT_INTERNAL_RESOURCE);
- f->store_32(resource_map[res]);
- //internal resource
- }
-
-
- } break;
- case Variant::INPUT_EVENT: {
-
- f->store_32(VARIANT_INPUT_EVENT);
- WARN_PRINT("Can't save InputEvent (maybe it could..)");
- } break;
- case Variant::DICTIONARY: {
-
- f->store_32(VARIANT_DICTIONARY);
- Dictionary d = p_property;
- f->store_32(d.size());
-
- List<Variant> keys;
- d.get_key_list(&keys);
-
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- //if (!_check_type(dict[E->get()]))
- // continue;
-
- write_property(0,E->get());
- write_property(0,d[E->get()]);
- }
-
-
- } break;
- case Variant::ARRAY: {
-
- f->store_32(VARIANT_ARRAY);
- Array a=p_property;
- f->store_32(a.size());
- for(int i=0;i<a.size();i++) {
-
- write_property(i,a[i]);
- }
-
- } break;
- case Variant::RAW_ARRAY: {
-
- f->store_32(VARIANT_RAW_ARRAY);
- DVector<uint8_t> arr = p_property;
- int len=arr.size();
- f->store_32(len);
- DVector<uint8_t>::Read r = arr.read();
- f->store_buffer(r.ptr(),len);
- _pad_buffer(len);
-
- } break;
- case Variant::INT_ARRAY: {
-
- f->store_32(VARIANT_INT_ARRAY);
- DVector<int> arr = p_property;
- int len=arr.size();
- f->store_32(len);
- DVector<int>::Read r = arr.read();
- for(int i=0;i<len;i++)
- f->store_32(r[i]);
-
- } break;
- case Variant::REAL_ARRAY: {
-
- f->store_32(VARIANT_REAL_ARRAY);
- DVector<real_t> arr = p_property;
- int len=arr.size();
- f->store_32(len);
- DVector<real_t>::Read r = arr.read();
- for(int i=0;i<len;i++) {
- f->store_real(r[i]);
- }
-
- } break;
- case Variant::STRING_ARRAY: {
-
- f->store_32(VARIANT_STRING_ARRAY);
- DVector<String> arr = p_property;
- int len=arr.size();
- f->store_32(len);
- DVector<String>::Read r = arr.read();
- for(int i=0;i<len;i++) {
- save_unicode_string(r[i]);
- }
-
- } break;
- case Variant::VECTOR3_ARRAY: {
-
- f->store_32(VARIANT_VECTOR3_ARRAY);
- DVector<Vector3> arr = p_property;
- int len=arr.size();
- f->store_32(len);
- DVector<Vector3>::Read r = arr.read();
- for(int i=0;i<len;i++) {
- f->store_real(r[i].x);
- f->store_real(r[i].y);
- f->store_real(r[i].z);
- }
-
- } break;
- case Variant::VECTOR2_ARRAY: {
-
- f->store_32(VARIANT_VECTOR2_ARRAY);
- DVector<Vector2> arr = p_property;
- int len=arr.size();
- f->store_32(len);
- DVector<Vector2>::Read r = arr.read();
- for(int i=0;i<len;i++) {
- f->store_real(r[i].x);
- f->store_real(r[i].y);
- }
-
- } break;
- case Variant::COLOR_ARRAY: {
-
- f->store_32(VARIANT_COLOR_ARRAY);
- DVector<Color> arr = p_property;
- int len=arr.size();
- f->store_32(len);
- DVector<Color>::Read r = arr.read();
- for(int i=0;i<len;i++) {
- f->store_real(r[i].r);
- f->store_real(r[i].g);
- f->store_real(r[i].b);
- f->store_real(r[i].a);
- }
-
- } break;
- default: {
-
- ERR_EXPLAIN("Invalid variant");
- ERR_FAIL();
- }
- }
-}
-
-
-void ObjectFormatSaverBinary::_find_resources(const Variant& p_variant) {
-
-
- switch(p_variant.get_type()) {
- case Variant::OBJECT: {
-
-
- RES res = p_variant.operator RefPtr();
-
- if (res.is_null())
- return;
-
- if (!bundle_resources && res->get_path().length() && res->get_path().find("::") == -1 )
- return;
-
- if (resource_map.has(res))
- return;
-
- List<PropertyInfo> property_list;
-
- res->get_property_list(&property_list);
-
- for(List<PropertyInfo>::Element *E=property_list.front();E;E=E->next()) {
-
- if (E->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && E->get().usage&PROPERTY_USAGE_BUNDLE)) {
-
- _find_resources(res->get(E->get().name));
- }
- }
-
- SavedObject *so = memnew( SavedObject );
- _save_obj(res.ptr(),so);
- so->meta=res.get_ref_ptr();
-
- resource_map[ res ] = saved_resources.size();
- saved_resources.push_back(so);
-
- } break;
-
- case Variant::ARRAY: {
-
- Array varray=p_variant;
- int len=varray.size();
- for(int i=0;i<len;i++) {
-
- Variant v=varray.get(i);
- _find_resources(v);
- }
-
- } break;
-
- case Variant::DICTIONARY: {
-
- Dictionary d=p_variant;
- List<Variant> keys;
- d.get_key_list(&keys);
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- Variant v = d[E->get()];
- _find_resources(v);
- }
- } break;
- default: {}
- }
-
-}
-Error ObjectFormatSaverBinary::_save_obj(const Object *p_object,SavedObject *so) {
-
- if (optimizer.is_valid()) {
- //use optimizer
-
- List<OptimizedSaver::Property> props;
- optimizer->get_property_list(p_object,&props);
-
- for(List<OptimizedSaver::Property>::Element *E=props.front();E;E=E->next()) {
-
- if (skip_editor && String(E->get().name).begins_with("__editor"))
- continue;
- _find_resources(E->get().value);
- SavedObject::SavedProperty sp;
-
- sp.name_idx=get_string_index(E->get().name);
- sp.value=E->get().value;
- so->properties.push_back(sp);
- }
-
- } else {
- //use classic way
- List<PropertyInfo> property_list;
- p_object->get_property_list( &property_list );
-
- for(List<PropertyInfo>::Element *E=property_list.front();E;E=E->next()) {
-
- if (skip_editor && E->get().name.begins_with("__editor"))
- continue;
- if (E->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && E->get().usage&PROPERTY_USAGE_BUNDLE)) {
-
- SavedObject::SavedProperty sp;
- sp.name_idx=get_string_index(E->get().name);
- sp.value = p_object->get(E->get().name);
- _find_resources(sp.value);
- so->properties.push_back(sp);
- }
- }
- }
-
- return OK;
-
-}
-
-Error ObjectFormatSaverBinary::save(const Object *p_object,const Variant &p_meta) {
-
- ERR_FAIL_COND_V(!f,ERR_UNCONFIGURED);
- ERR_EXPLAIN("write_object should supply either an object, a meta, or both");
- ERR_FAIL_COND_V(!p_object && p_meta.get_type()==Variant::NIL, ERR_INVALID_PARAMETER);
-
- SavedObject *so = memnew( SavedObject );
-
- if (p_object)
- so->type=p_object->get_type();
-
- _find_resources(p_meta);
- so->meta=p_meta;
- Error err = _save_obj(p_object,so);
- ERR_FAIL_COND_V( err, ERR_INVALID_DATA );
-
- saved_objects.push_back(so);
-
- return OK;
-}
-
-void ObjectFormatSaverBinary::save_unicode_string(const String& p_string) {
-
-
- CharString utf8 = p_string.utf8();
- f->store_32(utf8.length()+1);
- f->store_buffer((const uint8_t*)utf8.get_data(),utf8.length()+1);
-}
-
-ObjectFormatSaverBinary::ObjectFormatSaverBinary(FileAccess *p_file,const String& p_magic,const String& p_local_path,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer) {
-
- optimizer=p_optimizer;
- relative_paths=p_flags&ObjectSaver::FLAG_RELATIVE_PATHS;
- skip_editor=p_flags&ObjectSaver::FLAG_OMIT_EDITOR_PROPERTIES;
- bundle_resources=p_flags&ObjectSaver::FLAG_BUNDLE_RESOURCES;
- big_endian=p_flags&ObjectSaver::FLAG_SAVE_BIG_ENDIAN;
- f=p_file; // should be already opened
- local_path=p_local_path;
- magic=p_magic;
-
- bin_meta_idx = get_string_index("__bin_meta__"); //is often used, so create
-}
-
-int ObjectFormatSaverBinary::get_string_index(const String& p_string) {
-
- StringName s=p_string;
- if (string_map.has(s))
- return string_map[s];
-
- string_map[s]=strings.size();
- strings.push_back(s);
- return strings.size()-1;
-}
-
-ObjectFormatSaverBinary::~ObjectFormatSaverBinary() {
-
-
- static const uint8_t header[4]={'O','B','D','B'};
- f->store_buffer(header,4);
- if (big_endian) {
- f->store_32(1);
- f->set_endian_swap(true);
- } else
- f->store_32(0);
-
- f->store_32(0); //64 bits file, false for now
- f->store_32(VERSION_MAJOR);
- f->store_32(VERSION_MINOR);
- save_unicode_string(magic);
- for(int i=0;i<16;i++)
- f->store_32(0); // reserved
-
- f->store_32(strings.size()); //string table size
- for(int i=0;i<strings.size();i++) {
- print_bl("saving string: "+strings[i]);
- save_unicode_string(strings[i]);
- }
-
- // save resources
-
- for(int i=0;i<saved_resources.size();i++) {
-
- SavedObject *so = saved_resources[i];
- RES res = so->meta;
- ERR_CONTINUE(!resource_map.has(res));
-
- f->store_32(SECTION_RESOURCE);
- size_t skip_pos = f->get_pos();
- f->store_64(0); // resource skip seek pos
- save_unicode_string(res->get_type());
-
- if (res->get_path().length() && res->get_path().find("::") == -1 )
- save_unicode_string(res->get_path());
- else
- save_unicode_string("local://"+itos(i));
-
-
-
- List<SavedObject::SavedProperty>::Element *SE = so->properties.front();
-
- while(SE) {
-
- write_property(SE->get().name_idx,SE->get().value);
- SE=SE->next();
- }
-
- f->store_32(SECTION_END);
-
- size_t end=f->get_pos();
- f->seek(skip_pos);
- f->store_64(end);
- f->seek_end();
-
- memdelete( so );
- }
-
- if (!saved_objects.empty()) {
-
-
- for(List<SavedObject*>::Element *E=saved_objects.front();E;E=E->next()) {
-
- SavedObject *so = E->get();
-
-
- size_t section_end;
-
- if (so->type!="") {
- f->store_32(SECTION_OBJECT);
- section_end=f->get_pos();
- f->store_64(0); //section end
- save_unicode_string(so->type);
- } else {
- f->store_32(SECTION_META_OBJECT);
- section_end=f->get_pos();
- f->store_64(0); //section end
- }
-
-
- if (so->meta.get_type()!=Variant::NIL)
- write_property(bin_meta_idx,so->meta);
-
- List<SavedObject::SavedProperty>::Element *SE = so->properties.front();
-
- while(SE) {
-
- write_property(SE->get().name_idx,SE->get().value);
- SE=SE->next();
- }
-
- f->store_32(SECTION_END);
-
- size_t end=f->get_pos();
- f->seek(section_end);
- f->store_64(end);
- f->seek_end();
-
- memdelete(so); //no longer needed
- }
-
-
- }
-
- f->store_32(SECTION_END);
-
- f->close();
- memdelete(f);
-}
-
-
-ObjectFormatSaver* ObjectFormatSaverInstancerBinary::instance(const String& p_file,const String& p_magic,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer) {
-
- FileAccess *f = FileAccess::open(p_file, FileAccess::WRITE);
-
- ERR_FAIL_COND_V( !f, NULL );
- String local_path = Globals::get_singleton()->localize_path(p_file);
-
- return memnew( ObjectFormatSaverBinary( f, p_magic,local_path,p_flags,p_optimizer ) );
-}
-
-void ObjectFormatSaverInstancerBinary::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("bin");
-}
-
-
-ObjectFormatSaverInstancerBinary::~ObjectFormatSaverInstancerBinary() {
-
-
-}
-
-
-
-/************************************************/
-/************************************************/
-/************************************************/
-/************************************************/
-/************************************************/
-
-
-void ObjectFormatLoaderBinary::_advance_padding(uint32_t p_len) {
-
- uint32_t extra = 4-(p_len%4);
- if (extra<4) {
- for(uint32_t i=0;i<extra;i++)
- f->get_8(); //pad to 32
- }
-
-}
-
-Error ObjectFormatLoaderBinary::parse_property(Variant& r_v, int &r_index) {
-
-
- uint32_t prop = f->get_32();
- if (prop==SECTION_END)
- return ERR_FILE_EOF;
- ERR_FAIL_COND_V(prop!=SECTION_PROPERTY,ERR_FILE_CORRUPT);
-
- r_index = f->get_32();
-
- uint32_t type = f->get_32();
- print_bl("find property of type: "+itos(type));
-
-
- switch(type) {
-
- case VARIANT_NIL: {
-
- r_v=Variant();
- } break;
- case VARIANT_BOOL: {
-
- r_v=bool(f->get_32());
- } break;
- case VARIANT_INT: {
-
- r_v=int(f->get_32());
- } break;
- case VARIANT_REAL: {
-
- r_v=f->get_real();
- } break;
- case VARIANT_STRING: {
-
- r_v=get_unicode_string();
- } break;
- case VARIANT_VECTOR2: {
-
- Vector2 v;
- v.x=f->get_real();
- v.y=f->get_real();
- r_v=v;
-
- } break;
- case VARIANT_RECT2: {
-
- Rect2 v;
- v.pos.x=f->get_real();
- v.pos.y=f->get_real();
- v.size.x=f->get_real();
- v.size.y=f->get_real();
- r_v=v;
-
- } break;
- case VARIANT_VECTOR3: {
-
- Vector3 v;
- v.x=f->get_real();
- v.y=f->get_real();
- v.z=f->get_real();
- r_v=v;
- } break;
- case VARIANT_PLANE: {
-
- Plane v;
- v.normal.x=f->get_real();
- v.normal.y=f->get_real();
- v.normal.z=f->get_real();
- v.d=f->get_real();
- r_v=v;
- } break;
- case VARIANT_QUAT: {
- Quat v;
- v.x=f->get_real();
- v.y=f->get_real();
- v.z=f->get_real();
- v.w=f->get_real();
- r_v=v;
-
- } break;
- case VARIANT_AABB: {
-
- AABB v;
- v.pos.x=f->get_real();
- v.pos.y=f->get_real();
- v.pos.z=f->get_real();
- v.size.x=f->get_real();
- v.size.y=f->get_real();
- v.size.z=f->get_real();
- r_v=v;
-
- } break;
- case VARIANT_MATRIX32: {
-
- Matrix32 v;
- v.elements[0].x=f->get_real();
- v.elements[0].y=f->get_real();
- v.elements[1].x=f->get_real();
- v.elements[1].y=f->get_real();
- v.elements[2].x=f->get_real();
- v.elements[2].y=f->get_real();
- r_v=v;
-
- } break;
- case VARIANT_MATRIX3: {
-
- Matrix3 v;
- v.elements[0].x=f->get_real();
- v.elements[0].y=f->get_real();
- v.elements[0].z=f->get_real();
- v.elements[1].x=f->get_real();
- v.elements[1].y=f->get_real();
- v.elements[1].z=f->get_real();
- v.elements[2].x=f->get_real();
- v.elements[2].y=f->get_real();
- v.elements[2].z=f->get_real();
- r_v=v;
-
- } break;
- case VARIANT_TRANSFORM: {
-
- Transform v;
- v.basis.elements[0].x=f->get_real();
- v.basis.elements[0].y=f->get_real();
- v.basis.elements[0].z=f->get_real();
- v.basis.elements[1].x=f->get_real();
- v.basis.elements[1].y=f->get_real();
- v.basis.elements[1].z=f->get_real();
- v.basis.elements[2].x=f->get_real();
- v.basis.elements[2].y=f->get_real();
- v.basis.elements[2].z=f->get_real();
- v.origin.x=f->get_real();
- v.origin.y=f->get_real();
- v.origin.z=f->get_real();
- r_v=v;
- } break;
- case VARIANT_COLOR: {
-
- Color v;
- v.r=f->get_real();
- v.g=f->get_real();
- v.b=f->get_real();
- v.a=f->get_real();
- r_v=v;
-
- } break;
- case VARIANT_IMAGE: {
-
-
- uint32_t encoding = f->get_32();
- if (encoding==IMAGE_ENCODING_EMPTY) {
- r_v=Variant();
- break;
- }
-
- if (encoding==IMAGE_ENCODING_RAW) {
- uint32_t width = f->get_32();
- uint32_t height = f->get_32();
- uint32_t mipmaps = f->get_32();
- uint32_t format = f->get_32();
- Image::Format fmt;
- switch(format) {
-
- case IMAGE_FORMAT_GRAYSCALE: { fmt=Image::FORMAT_GRAYSCALE; } break;
- case IMAGE_FORMAT_INTENSITY: { fmt=Image::FORMAT_INTENSITY; } break;
- case IMAGE_FORMAT_GRAYSCALE_ALPHA: { fmt=Image::FORMAT_GRAYSCALE_ALPHA; } break;
- case IMAGE_FORMAT_RGB: { fmt=Image::FORMAT_RGB; } break;
- case IMAGE_FORMAT_RGBA: { fmt=Image::FORMAT_RGBA; } break;
- case IMAGE_FORMAT_INDEXED: { fmt=Image::FORMAT_INDEXED; } break;
- case IMAGE_FORMAT_INDEXED_ALPHA: { fmt=Image::FORMAT_INDEXED_ALPHA; } break;
- case IMAGE_FORMAT_BC1: { fmt=Image::FORMAT_BC1; } break;
- case IMAGE_FORMAT_BC2: { fmt=Image::FORMAT_BC2; } break;
- case IMAGE_FORMAT_BC3: { fmt=Image::FORMAT_BC3; } break;
- case IMAGE_FORMAT_BC4: { fmt=Image::FORMAT_BC4; } break;
- case IMAGE_FORMAT_BC5: { fmt=Image::FORMAT_BC5; } break;
- case IMAGE_FORMAT_CUSTOM: { fmt=Image::FORMAT_CUSTOM; } break;
- default: {
-
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- }
-
-
- uint32_t datalen = f->get_32();
-
- print_bl("width: "+itos(width));
- print_bl("height: "+itos(height));
- print_bl("mipmaps: "+itos(mipmaps));
- print_bl("format: "+itos(format));
- print_bl("datalen: "+itos(datalen));
-
- DVector<uint8_t> imgdata;
- imgdata.resize(datalen);
- DVector<uint8_t>::Write w = imgdata.write();
- f->get_buffer(w.ptr(),datalen);
- _advance_padding(datalen);
- w=DVector<uint8_t>::Write();
-
- r_v=Image(width,height,mipmaps,fmt,imgdata);
- }
-
-
- } break;
- case VARIANT_NODE_PATH: {
-
- r_v=NodePath(get_unicode_string());
- } break;
- case VARIANT_RID: {
-
- r_v=f->get_32();
- } break;
- case VARIANT_OBJECT: {
-
- uint32_t type=f->get_32();
-
- switch(type) {
-
- case OBJECT_EMPTY: {
- //do none
-
- } break;
- case OBJECT_INTERNAL_RESOURCE: {
- uint32_t index=f->get_32();
- String path = local_path+"::"+itos(index);
- RES res = ResourceLoader::load(path);
- if (res.is_null()) {
- WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data());
- }
- r_v=res;
-
- } break;
- case OBJECT_EXTERNAL_RESOURCE: {
-
- String type = get_unicode_string();
- String path = get_unicode_string();
-
- if (path.find("://")==-1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- path=Globals::get_singleton()->localize_path(local_path.get_base_dir()+"/"+path);
-
- }
-
- RES res=ResourceLoader::load(path,type);
-
- if (res.is_null()) {
- WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data());
- }
- r_v=res;
-
- } break;
- default: {
-
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- } break;
- }
-
- } break;
- case VARIANT_INPUT_EVENT: {
-
- } break;
- case VARIANT_DICTIONARY: {
-
- int len=f->get_32();
- Dictionary d;
- for(int i=0;i<len;i++) {
- int idx;
- Variant key;
- Error err = parse_property(key,idx);
- ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
- Variant value;
- err = parse_property(value,idx);
- ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
- d[key]=value;
- }
- r_v=d;
- } break;
- case VARIANT_ARRAY: {
- int len=f->get_32();
- Array a;
- a.resize(len);
- for(int i=0;i<len;i++) {
- int idx;
- Variant val;
- Error err = parse_property(val,idx);
- ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
- a[i]=val;
- }
- r_v=a;
-
- } break;
- case VARIANT_RAW_ARRAY: {
-
- uint32_t len = f->get_32();
-
- DVector<uint8_t> array;
- array.resize(len);
- DVector<uint8_t>::Write w = array.write();
- f->get_buffer(w.ptr(),len);
- _advance_padding(len);
- w=DVector<uint8_t>::Write();
- r_v=array;
-
- } break;
- case VARIANT_INT_ARRAY: {
-
- uint32_t len = f->get_32();
-
- DVector<int> array;
- array.resize(len);
- DVector<int>::Write w = array.write();
- f->get_buffer((uint8_t*)w.ptr(),len*4);
- w=DVector<int>::Write();
- r_v=array;
- } break;
- case VARIANT_REAL_ARRAY: {
-
- uint32_t len = f->get_32();
-
- DVector<real_t> array;
- array.resize(len);
- DVector<real_t>::Write w = array.write();
- f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t));
- w=DVector<real_t>::Write();
- r_v=array;
- } break;
- case VARIANT_STRING_ARRAY: {
-
- uint32_t len = f->get_32();
- DVector<String> array;
- array.resize(len);
- DVector<String>::Write w = array.write();
- for(int i=0;i<len;i++)
- w[i]=get_unicode_string();
- w=DVector<String>::Write();
- r_v=array;
-
-
- } break;
- case VARIANT_VECTOR2_ARRAY: {
-
- uint32_t len = f->get_32();
-
- DVector<Vector2> array;
- array.resize(len);
- DVector<Vector2>::Write w = array.write();
- if (sizeof(Vector2)==8) {
- f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t)*2);
- } else {
- ERR_EXPLAIN("Vector2 size is NOT 8!");
- ERR_FAIL_V(ERR_UNAVAILABLE);
- }
- w=DVector<Vector2>::Write();
- r_v=array;
-
- } break;
- case VARIANT_VECTOR3_ARRAY: {
-
- uint32_t len = f->get_32();
-
- DVector<Vector3> array;
- array.resize(len);
- DVector<Vector3>::Write w = array.write();
- if (sizeof(Vector3)==12) {
- f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t)*3);
- } else {
- ERR_EXPLAIN("Vector3 size is NOT 12!");
- ERR_FAIL_V(ERR_UNAVAILABLE);
- }
- w=DVector<Vector3>::Write();
- r_v=array;
-
- } break;
- case VARIANT_COLOR_ARRAY: {
-
- uint32_t len = f->get_32();
-
- DVector<Color> array;
- array.resize(len);
- DVector<Color>::Write w = array.write();
- if (sizeof(Color)==16) {
- f->get_buffer((uint8_t*)w.ptr(),len*sizeof(real_t)*4);
- } else {
- ERR_EXPLAIN("Color size is NOT 16!");
- ERR_FAIL_V(ERR_UNAVAILABLE);
- }
- w=DVector<Color>::Write();
- r_v=array;
- } break;
-
- default: {
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- } break;
- }
-
-
-
- return OK; //never reach anyway
-
-}
-
-Error ObjectFormatLoaderBinary::load(Object **p_object,Variant &p_meta) {
-
-
-
- while(true) {
-
- if (f->eof_reached()) {
- ERR_EXPLAIN("Premature end of file at: "+local_path);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- RES resource;
- Object *obj=NULL;
- bool meta=false;
-
- uint32_t section = f->get_32();
-
- switch(section) {
-
-
- case SECTION_RESOURCE: {
-
- print_bl("resource found");
-
- size_t section_end = f->get_64();
- print_bl("section end: "+itos(section_end));
- String type = get_unicode_string();
- String path = get_unicode_string();
- print_bl("path: "+path);
-
- if (path.begins_with("local://")) {
- //built-in resource (but really external)
- path=path.replace("local://",local_path+"::");
- }
-
- if (ResourceCache::has(path)) {
- f->seek(section_end);
- continue;
- }
-
- //load properties
-
-
- obj = ObjectTypeDB::instance(type);
- if (!obj) {
- ERR_EXPLAIN("Object of unrecognized type '"+type+"' in file: "+type);
- }
-
- ERR_FAIL_COND_V(!obj,ERR_FILE_CORRUPT);
-
- Resource *r = obj->cast_to<Resource>();
- if (!r) {
- memdelete(obj); //bye
- ERR_EXPLAIN("Object type in resource field not a resource, type is: "+obj->get_type());
- ERR_FAIL_COND_V(!obj->cast_to<Resource>(),ERR_FILE_CORRUPT);
- }
-
- resource = RES( r );
- r->set_path(path);
- } break;
- case SECTION_META_OBJECT:
- meta=true;
- print_bl("meta found");
-
- case SECTION_OBJECT: {
-
- uint64_t section_end = f->get_64();
-
- if (!meta) {
- print_bl("object");
-
- String type = get_unicode_string();
- if (ObjectTypeDB::can_instance(type)) {
- obj = ObjectTypeDB::instance(type);
- if (!obj) {
- ERR_EXPLAIN("Object of unrecognized type in file: "+type);
- }
- ERR_FAIL_COND_V(!obj,ERR_FILE_CORRUPT);
- } else {
-
- f->seek(section_end);
- return ERR_SKIP;
- };
-
-
- }
-
-
- } break;
- case SECTION_END: {
-
-
- return ERR_FILE_EOF;
- } break;
-
- default: {
-
- ERR_EXPLAIN("Invalid Section ID '"+itos(section)+"' in file: "+local_path);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
-
- }
-
- }
-
-
- //load properties
-
- while(true) {
-
- int name_idx;
- Variant v;
- Error err;
- err = parse_property(v,name_idx);
-
- print_bl("prop idx "+itos(name_idx)+" value: "+String(v));
-
- if (err==ERR_FILE_EOF)
- break;
-
- if (err!=OK) {
- ERR_EXPLAIN("File Corrupted");
- ERR_FAIL_COND_V(err!=OK,ERR_FILE_CORRUPT);
- }
-
-
- if (resource.is_null() && name_idx==0) { //0 is __bin_meta__
-
- p_meta=v;
- continue;
- } else if (!obj) {
-
- ERR_EXPLAIN("Normal property found in meta object.");
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- Map<int,StringName>::Element *E=string_map.find(name_idx);
- if (!E) {
- ERR_EXPLAIN("Property ID has no matching name: "+itos(name_idx));
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- obj->set(E->get(),v);
- }
-
- if (!obj) {
- *p_object=NULL;
- return OK; // it was a meta object
- }
-
- if (resource.is_null()) {
-
- //regular object
- *p_object=obj;
- return OK;
- } else {
-
- resource_cache.push_back(resource); //keep it in mem until finished loading
- }
-
- }
-}
-
-
-ObjectFormatLoaderBinary::~ObjectFormatLoaderBinary() {
-
- if (f) {
- if (f->is_open())
- f->close();
- memdelete(f);
- }
-}
-
-
-String ObjectFormatLoaderBinary::get_unicode_string() {
-
- uint32_t len = f->get_32();
- if (len>str_buf.size()) {
- str_buf.resize(len);
- }
- f->get_buffer((uint8_t*)&str_buf[0],len);
- String s;
- s.parse_utf8(&str_buf[0]);
- return s;
-}
-
-ObjectFormatLoaderBinary::ObjectFormatLoaderBinary(FileAccess *p_f,bool p_endian_swap,bool p_use64) {
-
- f=p_f;
- endian_swap=p_endian_swap;
- use_real64=p_use64;
-
- //load string table
- uint32_t string_table_size = f->get_32();
- print_bl("string table size: "+itos(string_table_size));
- for(int i=0;i<string_table_size;i++) {
-
- String str = get_unicode_string();
- print_bl("string "+itos(i)+" is: "+str);
- string_map[i]=str;
- }
-
-
-}
-
-ObjectFormatLoaderBinary* ObjectFormatLoaderInstancerBinary::instance(const String& p_file,const String& p_magic) {
-
- FileAccess *f=FileAccess::open(p_file,FileAccess::READ);
- ERR_FAIL_COND_V(!f,NULL);
-
- uint8_t header[4];
- f->get_buffer(header,4);
- if (header[0]!='O' || header[1]!='B' || header[2]!='D' || header[3]!='B') {
-
- ERR_EXPLAIN("File not in valid binary format: "+p_file);
- ERR_FAIL_V(NULL);
- }
-
- uint32_t big_endian = f->get_32();
-#ifdef BIG_ENDIAN_ENABLED
- bool endian_swap = !big_endian;
-#else
- bool endian_swap = big_endian;
-#endif
-
- bool use_real64 = f->get_32();
-
- f->set_endian_swap(big_endian!=0); //read big endian if saved as big endian
-
- uint32_t ver_major=f->get_32();
- uint32_t ver_minor=f->get_32();
-
- print_bl("big endian: "+itos(big_endian));
- print_bl("endian swap: "+itos(endian_swap));
- print_bl("real64: "+itos(use_real64));
- print_bl("major: "+itos(ver_major));
- print_bl("minor: "+itos(ver_minor));
-
- if (ver_major>VERSION_MAJOR || (ver_major==VERSION_MAJOR && ver_minor>VERSION_MINOR)) {
-
- f->close();
- memdelete(f);
- ERR_EXPLAIN("File Format '"+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+p_file);
- ERR_FAIL_V(NULL);
-
- }
-
- uint32_t magic_len = f->get_32();
- Vector<char> magic;
- magic.resize(magic_len);
- f->get_buffer((uint8_t*)&magic[0],magic_len);
- String magic_str;
- magic_str.parse_utf8(&magic[0]);
-
- print_bl("magic: "+magic_str);
- if (magic_str!=p_magic) {
-
- f->close();
- memdelete(f);
- ERR_EXPLAIN("File magic mismatch, found '"+magic_str+"' in : "+p_file);
- ERR_FAIL_V(NULL);
- }
-
- print_bl("skipping 32");
- for(int i=0;i<16;i++)
- f->get_32(); //skip a few reserved fields
-
- if (f->eof_reached()) {
-
- f->close();
- memdelete(f);
- ERR_EXPLAIN("Premature End Of File: "+p_file);
- ERR_FAIL_V(NULL);
-
- }
-
- print_bl("creating loader");
- ObjectFormatLoaderBinary *loader = memnew( ObjectFormatLoaderBinary(f,endian_swap,use_real64) );
- loader->local_path=p_file;
-
- return loader;
-}
-
-void ObjectFormatLoaderInstancerBinary::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("bin");
-}
-
-
-#endif
diff --git a/core/io/object_format_binary.h b/core/io/object_format_binary.h
deleted file mode 100644
index aaf6bf357a..0000000000
--- a/core/io/object_format_binary.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*************************************************************************/
-/* object_format_binary.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 OBJECT_FORMAT_BINARY_H
-#define OBJECT_FORMAT_BINARY_H
-
-#include "object_loader.h"
-#include "object_saver_base.h"
-#include "dvector.h"
-#include "core/os/file_access.h"
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-
-class ObjectFormatSaverBinary : public ObjectFormatSaver {
-
- String local_path;
-
-
- Ref<OptimizedSaver> optimizer;
-
- bool relative_paths;
- bool bundle_resources;
- bool skip_editor;
- bool big_endian;
- int bin_meta_idx;
- FileAccess *f;
- String magic;
- Map<RES,int> resource_map;
- Map<StringName,int> string_map;
- Vector<StringName> strings;
-
- struct SavedObject {
-
- Variant meta;
- String type;
-
-
- struct SavedProperty {
-
- int name_idx;
- Variant value;
- };
-
- List<SavedProperty> properties;
- };
-
-
- int get_string_index(const String& p_string);
- void save_unicode_string(const String& p_string);
-
- List<SavedObject*> saved_objects;
- List<SavedObject*> saved_resources;
-
- void _pad_buffer(int p_bytes);
- Error _save_obj(const Object *p_object,SavedObject *so);
- void _find_resources(const Variant& p_variant);
- void write_property(int p_idx,const Variant& p_property);
-
-
-public:
-
- virtual Error save(const Object *p_object,const Variant &p_meta);
-
- ObjectFormatSaverBinary(FileAccess *p_file,const String& p_magic,const String& p_local_path,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer);
- ~ObjectFormatSaverBinary();
-};
-
-class ObjectFormatSaverInstancerBinary : public ObjectFormatSaverInstancer {
-public:
-
- virtual ObjectFormatSaver* instance(const String& p_file,const String& p_magic,uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>());
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
- virtual ~ObjectFormatSaverInstancerBinary();
-};
-
-
-
-
-/***********************************/
-/***********************************/
-/***********************************/
-/***********************************/
-
-class ObjectFormatLoaderBinary : public ObjectFormatLoader {
-
- String local_path;
-
- FileAccess *f;
-
- bool endian_swap;
- bool use_real64;
-
- Vector<char> str_buf;
- List<RES> resource_cache;
-
- Map<int,StringName> string_map;
-
- String get_unicode_string();
- void _advance_padding(uint32_t p_len);
-
-friend class ObjectFormatLoaderInstancerBinary;
-
-
- Error parse_property(Variant& r_v, int& r_index);
-
-public:
-
-
- virtual Error load(Object **p_object,Variant &p_meta);
-
- ObjectFormatLoaderBinary(FileAccess *f,bool p_endian_swap,bool p_use64);
- virtual ~ObjectFormatLoaderBinary();
-};
-
-class ObjectFormatLoaderInstancerBinary : public ObjectFormatLoaderInstancer {
-public:
-
- virtual ObjectFormatLoaderBinary* instance(const String& p_file,const String& p_magic);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
-
-
-};
-
-
-
-#endif // OBJECT_FORMAT_BINARY_H
-#endif
diff --git a/core/io/object_format_xml.cpp b/core/io/object_format_xml.cpp
deleted file mode 100644
index 0a8ce70d5e..0000000000
--- a/core/io/object_format_xml.cpp
+++ /dev/null
@@ -1,3190 +0,0 @@
-/*************************************************************************/
-/* object_format_xml.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 XML_ENABLED
-#ifdef OLD_SCENE_FORMAT_ENABLED
-#include "object_format_xml.h"
-#include "resource.h"
-#include "io/resource_loader.h"
-#include "print_string.h"
-#include "object_type_db.h"
-#include "globals.h"
-#include "os/os.h"
-#include "version.h"
-
-void ObjectFormatSaverXML::escape(String& p_str) {
-
- p_str=p_str.replace("&","&amp;");
- p_str=p_str.replace("<","&gt;");
- p_str=p_str.replace(">","&lt;");
- p_str=p_str.replace("'","&apos;");
- p_str=p_str.replace("\"","&quot;");
- for (int i=1;i<32;i++) {
-
- char chr[2]={i,0};
- p_str=p_str.replace(chr,"&#"+String::num(i)+";");
- }
-
-
-}
-void ObjectFormatSaverXML::write_tabs(int p_diff) {
-
- for (int i=0;i<depth+p_diff;i++) {
-
- f->store_8('\t');
- }
-}
-
-void ObjectFormatSaverXML::write_string(String p_str,bool p_escape) {
-
- /* write an UTF8 string */
- if (p_escape)
- escape(p_str);
-
- f->store_string(p_str);;
- /*
- CharString cs=p_str.utf8();
- const char *data=cs.get_data();
-
- while (*data) {
- f->store_8(*data);
- data++;
- }*/
-
-
-}
-
-void ObjectFormatSaverXML::enter_tag(const String& p_section,const String& p_args) {
-
- if (p_args.length())
- write_string("<"+p_section+" "+p_args+">",false);
- else
- write_string("<"+p_section+">",false);
- depth++;
-}
-void ObjectFormatSaverXML::exit_tag(const String& p_section) {
-
- depth--;
- write_string("</"+p_section+">",false);
-
-}
-
-/*
-static bool _check_type(const Variant& p_property) {
-
- if (p_property.get_type()==Variant::_RID)
- return false;
- if (p_property.get_type()==Variant::OBJECT) {
- RES res = p_property;
- if (res.is_null())
- return false;
- }
-
- return true;
-}*/
-
-void ObjectFormatSaverXML::write_property(const String& p_name,const Variant& p_property,bool *r_ok) {
-
- if (r_ok)
- *r_ok=false;
-
- String type;
- String params;
- bool oneliner=true;
-
- switch( p_property.get_type() ) {
-
- case Variant::NIL: type="nil"; break;
- case Variant::BOOL: type="bool"; break;
- case Variant::INT: type="int"; break;
- case Variant::REAL: type="real"; break;
- case Variant::STRING: type="string"; break;
- case Variant::VECTOR2: type="vector2"; break;
- case Variant::RECT2: type="rect2"; break;
- case Variant::VECTOR3: type="vector3"; break;
- case Variant::PLANE: type="plane"; break;
- case Variant::_AABB: type="aabb"; break;
- case Variant::QUAT: type="quaternion"; break;
- case Variant::MATRIX32: type="matrix32"; break;
- case Variant::MATRIX3: type="matrix3"; break;
- case Variant::TRANSFORM: type="transform"; break;
- case Variant::COLOR: type="color"; break;
- case Variant::IMAGE: {
- type="image";
- Image img=p_property;
- if (img.empty()) {
- enter_tag(type,"name=\""+p_name+"\"");
- exit_tag(type);
- if (r_ok)
- *r_ok=true;
- return;
- }
- params+="encoding=\"raw\"";
- params+=" width=\""+itos(img.get_width())+"\"";
- params+=" height=\""+itos(img.get_height())+"\"";
- params+=" mipmaps=\""+itos(img.get_mipmaps())+"\"";
-
- switch(img.get_format()) {
-
- case Image::FORMAT_GRAYSCALE: params+=" format=\"grayscale\""; break;
- case Image::FORMAT_INTENSITY: params+=" format=\"intensity\""; break;
- case Image::FORMAT_GRAYSCALE_ALPHA: params+=" format=\"grayscale_alpha\""; break;
- case Image::FORMAT_RGB: params+=" format=\"rgb\""; break;
- case Image::FORMAT_RGBA: params+=" format=\"rgba\""; break;
- case Image::FORMAT_INDEXED : params+=" format=\"indexed\""; break;
- case Image::FORMAT_INDEXED_ALPHA: params+=" format=\"indexed_alpha\""; break;
- case Image::FORMAT_BC1: params+=" format=\"bc1\""; break;
- case Image::FORMAT_BC2: params+=" format=\"bc2\""; break;
- case Image::FORMAT_BC3: params+=" format=\"bc3\""; break;
- case Image::FORMAT_BC4: params+=" format=\"bc4\""; break;
- case Image::FORMAT_BC5: params+=" format=\"bc5\""; break;
- case Image::FORMAT_CUSTOM: params+=" format=\"custom\" custom_size=\""+itos(img.get_data().size())+"\""; break;
- default: {}
- }
- } break;
- case Variant::NODE_PATH: type="node_path"; break;
- case Variant::OBJECT: {
- type="resource";
- RES res = p_property;
- if (res.is_null()) {
- enter_tag(type,"name=\""+p_name+"\"");
- exit_tag(type);
- if (r_ok)
- *r_ok=true;
-
- return; // don't save it
- }
-
- params="resource_type=\""+res->get_type()+"\"";
-
- if (res->get_path().length() && res->get_path().find("::")==-1) {
- //external resource
- String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
- escape(path);
- params+=" path=\""+path+"\"";
- } else {
-
- //internal resource
- ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
- ERR_FAIL_COND(!resource_map.has(res));
-
- params+=" path=\"local://"+itos(resource_map[res])+"\"";
- }
-
- } break;
- case Variant::INPUT_EVENT: type="input_event"; break;
- case Variant::DICTIONARY: type="dictionary" ; oneliner=false; break;
- case Variant::ARRAY: type="array"; params="len=\""+itos(p_property.operator Array().size())+"\""; oneliner=false; break;
-
- case Variant::RAW_ARRAY: type="raw_array"; params="len=\""+itos(p_property.operator DVector < uint8_t >().size())+"\""; break;
- case Variant::INT_ARRAY: type="int_array"; params="len=\""+itos(p_property.operator DVector < int >().size())+"\""; break;
- case Variant::REAL_ARRAY: type="real_array"; params="len=\""+itos(p_property.operator DVector < real_t >().size())+"\""; break;
- case Variant::STRING_ARRAY: type="string_array"; params="len=\""+itos(p_property.operator DVector < String >().size())+"\""; break;
- case Variant::VECTOR2_ARRAY: type="vector2_array"; params="len=\""+itos(p_property.operator DVector < Vector2 >().size())+"\""; break;
- case Variant::VECTOR3_ARRAY: type="vector3_array"; params="len=\""+itos(p_property.operator DVector < Vector3 >().size())+"\""; break;
- case Variant::COLOR_ARRAY: type="color_array"; params="len=\""+itos(p_property.operator DVector < Color >().size())+"\""; break;
- default: {
-
- ERR_PRINT("Unknown Variant type.");
- ERR_FAIL();
- }
-
- }
-
- write_tabs();
-
- if (p_name!="") {
- if (params.length())
- enter_tag(type,"name=\""+p_name+"\" "+params);
- else
- enter_tag(type,"name=\""+p_name+"\"");
- } else {
- if (params.length())
- enter_tag(type," "+params);
- else
- enter_tag(type,"");
- }
-
- if (!oneliner)
- write_string("\n",false);
- else
- write_string(" ",false);
-
-
- switch( p_property.get_type() ) {
-
- case Variant::NIL: {
-
- } break;
- case Variant::BOOL: {
-
- write_string( p_property.operator bool() ? "True":"False" );
- } break;
- case Variant::INT: {
-
- write_string( itos(p_property.operator int()) );
- } break;
- case Variant::REAL: {
-
- write_string( rtos(p_property.operator real_t()) );
- } break;
- case Variant::STRING: {
-
- String str=p_property;
- escape(str);
- str="\""+str+"\"";
- write_string( str,false );
- } break;
- case Variant::VECTOR2: {
-
- Vector2 v = p_property;
- write_string( rtoss(v.x) +", "+rtoss(v.y) );
- } break;
- case Variant::RECT2: {
-
- Rect2 aabb = p_property;
- write_string( rtoss(aabb.pos.x) +", "+rtoss(aabb.pos.y) +", "+rtoss(aabb.size.x) +", "+rtoss(aabb.size.y) );
-
- } break;
- case Variant::VECTOR3: {
-
- Vector3 v = p_property;
- write_string( rtoss(v.x) +", "+rtoss(v.y)+", "+rtoss(v.z) );
- } break;
- case Variant::PLANE: {
-
- Plane p = p_property;
- write_string( rtoss(p.normal.x) +", "+rtoss(p.normal.y)+", "+rtoss(p.normal.z)+", "+rtoss(p.d) );
-
- } break;
- case Variant::_AABB: {
-
- AABB aabb = p_property;
- write_string( rtoss(aabb.pos.x) +", "+rtoss(aabb.pos.y) +", "+rtoss(aabb.pos.z) +", "+rtoss(aabb.size.x) +", "+rtoss(aabb.size.y) +", "+rtoss(aabb.size.z) );
-
- } break;
- case Variant::QUAT: {
-
- Quat quat = p_property;
- write_string( rtoss(quat.x)+", "+rtoss(quat.y)+", "+rtoss(quat.z)+", "+rtoss(quat.w)+", ");
-
- } break;
- case Variant::MATRIX32: {
-
- String s;
- Matrix32 m3 = p_property;
- for (int i=0;i<3;i++) {
- for (int j=0;j<2;j++) {
-
- if (i!=0 || j!=0)
- s+=", ";
- s+=rtoss( m3.elements[i][j] );
- }
- }
-
- write_string(s);
-
- } break;
- case Variant::MATRIX3: {
-
- String s;
- Matrix3 m3 = p_property;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
-
- if (i!=0 || j!=0)
- s+=", ";
- s+=rtoss( m3.elements[i][j] );
- }
- }
-
- write_string(s);
-
- } break;
- case Variant::TRANSFORM: {
-
- String s;
- Transform t = p_property;
- Matrix3 &m3 = t.basis;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
-
- if (i!=0 || j!=0)
- s+=", ";
- s+=rtoss( m3.elements[i][j] );
- }
- }
-
- s=s+", "+rtoss(t.origin.x) +", "+rtoss(t.origin.y)+", "+rtoss(t.origin.z);
-
- write_string(s);
- } break;
-
- // misc types
- case Variant::COLOR: {
-
- Color c = p_property;
- write_string( rtoss(c.r) +", "+rtoss(c.g)+", "+rtoss(c.b)+", "+rtoss(c.a) );
-
- } break;
- case Variant::IMAGE: {
-
- String s;
- Image img = p_property;
- DVector<uint8_t> data = img.get_data();
- int len = data.size();
- DVector<uint8_t>::Read r = data.read();
- const uint8_t *ptr=r.ptr();;
- for (int i=0;i<len;i++) {
-
- uint8_t byte = ptr[i];
- const char hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- char str[3]={ hex[byte>>4], hex[byte&0xF], 0};
- s+=str;
- }
-
- write_string(s);
- } break;
- case Variant::NODE_PATH: {
-
- String str=p_property;
- escape(str);
- str="\""+str+"\"";
- write_string( str,false);
-
- } break;
-
- case Variant::OBJECT: {
- /* this saver does not save resources in here
- RES res = p_property;
-
- if (!res.is_null()) {
-
- String path=res->get_path();
- if (!res->is_shared() || !path.length()) {
- // if no path, or path is from inside a scene
- write_object( *res );
- }
-
- }
- */
-
- } break;
- case Variant::INPUT_EVENT: {
-
- write_string( p_property.operator String() );
- } break;
- case Variant::DICTIONARY: {
-
- Dictionary dict = p_property;
-
-
- List<Variant> keys;
- dict.get_key_list(&keys);
-
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- //if (!_check_type(dict[E->get()]))
- // continue;
-
- bool ok;
- write_property("",E->get(),&ok);
- ERR_CONTINUE(!ok);
-
- write_property("",dict[E->get()],&ok);
- if (!ok)
- write_property("",Variant()); //at least make the file consistent..
- }
-
-
-
-
- } break;
- case Variant::ARRAY: {
-
- Array array = p_property;
- int len=array.size();
- for (int i=0;i<len;i++) {
-
- write_property("",array[i]);
-
- }
-
- } break;
-
- case Variant::RAW_ARRAY: {
-
- String s;
- DVector<uint8_t> data = p_property;
- int len = data.size();
- DVector<uint8_t>::Read r = data.read();
- const uint8_t *ptr=r.ptr();;
- for (int i=0;i<len;i++) {
-
- uint8_t byte = ptr[i];
- const char hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- char str[3]={ hex[byte>>4], hex[byte&0xF], 0};
- s+=str;
- }
-
- write_string(s,false);
-
- } break;
- case Variant::INT_ARRAY: {
-
- DVector<int> data = p_property;
- int len = data.size();
- DVector<int>::Read r = data.read();
- const int *ptr=r.ptr();;
- write_tabs();
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- write_string(", ",false);
-
- write_string(itos(ptr[i]),false);
- }
-
-
-
- } break;
- case Variant::REAL_ARRAY: {
-
- DVector<real_t> data = p_property;
- int len = data.size();
- DVector<real_t>::Read r = data.read();
- const real_t *ptr=r.ptr();;
- write_tabs();
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- write_string(", ",false);
- write_string(rtoss(ptr[i]),false);
- }
-
-
- } break;
- case Variant::STRING_ARRAY: {
-
- DVector<String> data = p_property;
- int len = data.size();
- DVector<String>::Read r = data.read();
- const String *ptr=r.ptr();;
- String s;
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- s+=", ";
- String str=ptr[i];
- escape(str);
- s=s+"\""+str+"\"";
- }
-
- write_string(s,false);
-
- } break;
- case Variant::VECTOR2_ARRAY: {
-
- DVector<Vector2> data = p_property;
- int len = data.size();
- DVector<Vector2>::Read r = data.read();
- const Vector2 *ptr=r.ptr();;
- write_tabs();
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- write_string(", ",false);
- write_string(rtoss(ptr[i].x),false);
- write_string(", "+rtoss(ptr[i].y),false);
-
- }
-
-
- } break;
- case Variant::VECTOR3_ARRAY: {
-
- DVector<Vector3> data = p_property;
- int len = data.size();
- DVector<Vector3>::Read r = data.read();
- const Vector3 *ptr=r.ptr();;
- write_tabs();
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- write_string(", ",false);
- write_string(rtoss(ptr[i].x),false);
- write_string(", "+rtoss(ptr[i].y),false);
- write_string(", "+rtoss(ptr[i].z),false);
-
- }
-
-
- } break;
- case Variant::COLOR_ARRAY: {
-
- DVector<Color> data = p_property;
- int len = data.size();
- DVector<Color>::Read r = data.read();
- const Color *ptr=r.ptr();;
- write_tabs();
-
- for (int i=0;i<len;i++) {
-
- if (i>0)
- write_string(", ",false);
-
- write_string(rtoss(ptr[i].r),false);
- write_string(", "+rtoss(ptr[i].g),false);
- write_string(", "+rtoss(ptr[i].b),false);
- write_string(", "+rtoss(ptr[i].a),false);
-
- }
-
- } break;
- default: {}
-
- }
- if (oneliner)
- write_string(" ");
- else
- write_tabs(-1);
- exit_tag(type);
-
- write_string("\n",false);
-
- if (r_ok)
- *r_ok=true;
-
-}
-
-
-void ObjectFormatSaverXML::_find_resources(const Variant& p_variant) {
-
-
- switch(p_variant.get_type()) {
- case Variant::OBJECT: {
-
-
-
- RES res = p_variant.operator RefPtr();
-
- if (res.is_null())
- return;
-
- if (!bundle_resources && res->get_path().length() && res->get_path().find("::") == -1 )
- return;
-
- if (resource_map.has(res))
- return;
-
- List<PropertyInfo> property_list;
-
- res->get_property_list( &property_list );
-
- List<PropertyInfo>::Element *I=property_list.front();
-
- while(I) {
-
- PropertyInfo pi=I->get();
-
- if (pi.usage&PROPERTY_USAGE_STORAGE || (bundle_resources && pi.usage&PROPERTY_USAGE_BUNDLE)) {
-
- Variant v=res->get(I->get().name);
- _find_resources(v);
- }
-
- I=I->next();
- }
-
- resource_map[ res ] = resource_map.size(); //saved after, so the childs it needs are available when loaded
- saved_resources.push_back(res);
-
- } break;
-
- case Variant::ARRAY: {
-
- Array varray=p_variant;
- int len=varray.size();
- for(int i=0;i<len;i++) {
-
- Variant v=varray.get(i);
- _find_resources(v);
- }
-
- } break;
-
- case Variant::DICTIONARY: {
-
- Dictionary d=p_variant;
- List<Variant> keys;
- d.get_key_list(&keys);
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- Variant v = d[E->get()];
- _find_resources(v);
- }
- } break;
- default: {}
- }
-
-}
-
-
-
-Error ObjectFormatSaverXML::save(const Object *p_object,const Variant &p_meta) {
-
- ERR_FAIL_COND_V(!f,ERR_UNCONFIGURED);
- ERR_EXPLAIN("write_object should supply either an object, a meta, or both");
- ERR_FAIL_COND_V(!p_object && p_meta.get_type()==Variant::NIL, ERR_INVALID_PARAMETER);
-
- SavedObject *so = memnew( SavedObject );
-
- if (p_object)
- so->type=p_object->get_type();
-
- _find_resources(p_meta);
- so->meta=p_meta;
-
- if (p_object) {
-
-
- if (optimizer.is_valid()) {
- //use optimizer
-
- List<OptimizedSaver::Property> props;
- optimizer->get_property_list(p_object,&props);
-
- for(List<OptimizedSaver::Property>::Element *E=props.front();E;E=E->next()) {
-
- if (skip_editor && String(E->get().name).begins_with("__editor"))
- continue;
- _find_resources(E->get().value);
- SavedObject::SavedProperty sp;
- sp.name=E->get().name;
- sp.value=E->get().value;
- so->properties.push_back(sp);
- }
-
- } else {
- //use classic way
- List<PropertyInfo> property_list;
- p_object->get_property_list( &property_list );
-
- for(List<PropertyInfo>::Element *E=property_list.front();E;E=E->next()) {
-
- if (skip_editor && E->get().name.begins_with("__editor"))
- continue;
- if (E->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && E->get().usage&PROPERTY_USAGE_BUNDLE)) {
-
- SavedObject::SavedProperty sp;
- sp.name=E->get().name;
- sp.value = p_object->get(E->get().name);
- _find_resources(sp.value);
- so->properties.push_back(sp);
- }
- }
- }
-
- }
-
- saved_objects.push_back(so);
-
- return OK;
-}
-
-ObjectFormatSaverXML::ObjectFormatSaverXML(FileAccess *p_file,const String& p_magic,const String& p_local_path,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer) {
-
- optimizer=p_optimizer;
- relative_paths=p_flags&ObjectSaver::FLAG_RELATIVE_PATHS;
- skip_editor=p_flags&ObjectSaver::FLAG_OMIT_EDITOR_PROPERTIES;
- bundle_resources=p_flags&ObjectSaver::FLAG_BUNDLE_RESOURCES;
- f=p_file; // should be already opened
- depth=0;
- local_path=p_local_path;
- magic=p_magic;
-}
-ObjectFormatSaverXML::~ObjectFormatSaverXML() {
-
- write_string("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>",false); //no escape
- write_string("\n",false);
- enter_tag("object_file","magic=\""+magic+"\" "+"version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\"");
- write_string("\n",false);
-
- // save resources
-
- for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
-
- RES res = E->get();
- ERR_CONTINUE(!resource_map.has(res));
-
- write_tabs();
- if (res->get_path().length() && res->get_path().find("::") == -1 )
- enter_tag("resource","type=\""+res->get_type()+"\" path=\""+res->get_path()+"\""); //bundled
- else
- enter_tag("resource","type=\""+res->get_type()+"\" path=\"local://"+itos(resource_map[res])+"\"");
-
- if (optimizer.is_valid()) {
-
- List<OptimizedSaver::Property> props;
- optimizer->get_property_list(res.ptr(),&props);
-
- for(List<OptimizedSaver::Property>::Element *E=props.front();E;E=E->next()) {
-
- if (skip_editor && String(E->get().name).begins_with("__editor"))
- continue;
-
- write_property(E->get().name,E->get().value);
- }
-
-
- } else {
-
- List<PropertyInfo> property_list;
- res->get_property_list(&property_list);
- for(List<PropertyInfo>::Element *PE = property_list.front();PE;PE=PE->next()) {
-
-
- if (skip_editor && PE->get().name.begins_with("__editor"))
- continue;
-
- if (PE->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && PE->get().usage&PROPERTY_USAGE_BUNDLE)) {
-
- String name = PE->get().name;
- Variant value = res->get(name);
- write_property(name,value);
- }
-
-
- }
-
- }
- write_tabs(-1);
- exit_tag("resource");
- write_string("\n",false);
- }
-
- if (!saved_objects.empty()) {
-
-
- for(List<SavedObject*>::Element *E=saved_objects.front();E;E=E->next()) {
-
- SavedObject *so = E->get();
-
-
-
- write_tabs();
- if (so->type!="")
- enter_tag("object","type=\""+so->type+"\"");
- else
- enter_tag("object");
- write_string("\n",false);
-
- if (so->meta.get_type()!=Variant::NIL) {
-
- write_property("__xml_meta__",so->meta);
-
- }
-
- List<SavedObject::SavedProperty>::Element *SE = so->properties.front();
-
- while(SE) {
-
- write_property(SE->get().name,SE->get().value);
- SE=SE->next();
- }
-
-
- write_tabs(-1);
- exit_tag("object");
- write_string("\n",false);
- memdelete(so); //no longer needed
- }
-
-
- } else {
-
- WARN_PRINT("File contains no saved objects.");
- }
-
- exit_tag("object_file");
- f->close();
- memdelete(f);
-}
-
-
-ObjectFormatSaver* ObjectFormatSaverInstancerXML::instance(const String& p_file,const String& p_magic,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer) {
-
- Error err;
- FileAccess *f = FileAccess::open(p_file, FileAccess::WRITE,&err);
-
- ERR_FAIL_COND_V( err, NULL );
- String local_path = Globals::get_singleton()->localize_path(p_file);
-
- return memnew( ObjectFormatSaverXML( f, p_magic,local_path,p_flags,p_optimizer ) );
-}
-
-void ObjectFormatSaverInstancerXML::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("xml");
-}
-
-
-ObjectFormatSaverInstancerXML::~ObjectFormatSaverInstancerXML() {
-
-
-}
-
-/************************************************/
-/************************************************/
-/************************************************/
-/************************************************/
-/************************************************/
-
-
-
-#ifdef OPTIMIZED_XML_LOADER
-
-#define IS_FLOAT_CHAR(m_c) \
- ((m_c>='0' && m_c<='9') || m_c=='e' || m_c=='-' || m_c=='+' || m_c=='.')
-
-#define XML_FAIL(m_cond,m_err) \
- if (m_cond) {\
- ERR_EXPLAIN(local_path+":"+itos(parser->get_current_line())+": "+String(m_err));\
- ERR_FAIL_COND_V( m_cond, ERR_FILE_CORRUPT );\
- }
-
-
-Error ObjectFormatLoaderXML::_parse_property(Variant& r_v,String& r_name) {
-
- XML_FAIL( parser->is_empty(), "unexpected empty tag");
-
- String type=parser->get_node_name();
- String name=parser->get_attribute_value_safe("name");
-
- r_v=Variant();
- r_name=name;
-
- if (type=="dictionary") {
-
- Dictionary d;
- int reading=0;
- Variant key;
- while(parser->read()==OK) {
-
- if (parser->get_node_type()==XMLParser::NODE_ELEMENT) {
- Error err;
- String tagname;
-
- if (reading==0) {
-
- err=_parse_property(key,tagname);
- XML_FAIL( err,"error parsing dictionary key: "+name);
- reading++;
- } else {
-
- reading=0;
- Variant value;
- err=_parse_property(value,tagname);
- XML_FAIL( err,"error parsing dictionary value: "+name);
- d[key]=value;
- }
-
- } else if (parser->get_node_type()==XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="dictionary") {
- r_v=d;
- return OK;
- }
- }
-
-
- XML_FAIL( true, "unexpected end of file while reading dictionary: "+name);
-
- } else if (type=="array") {
-
- XML_FAIL( !parser->has_attribute("len"), "array missing 'len' attribute");
-
- int len=parser->get_attribute_value("len").to_int();
-
- Array array;
- array.resize(len);
-
-
- Variant v;
- String tagname;
- int idx=0;
-
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type()==XMLParser::NODE_ELEMENT) {
-
- XML_FAIL( idx >= len, "array size mismatch (too many elements)");
- Error err;
- String tagname;
- Variant key;
-
- err=_parse_property(key,tagname);
- XML_FAIL( err,"error parsing element of array: "+name);
- array[idx]=key;
- idx++;
-
-
- } else if (parser->get_node_type()==XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="array") {
-
- XML_FAIL( idx != len, "array size mismatch (not "+itos(len)+"):"+name);
- r_v=array;
- return OK;
- }
- }
-
- XML_FAIL( true, "unexpected end of file while reading dictionary: "+name);
-
- } else if (type=="resource") {
-
-
- XML_FAIL(!parser->has_attribute("path"),"resource property has no 'path' set (embedding not supported).")
-
- String path=parser->get_attribute_value("path");
- String hint = parser->get_attribute_value_safe("resource_type");
-
- if (path.begins_with("local://"))
- path=path.replace("local://",local_path+"::");
- else if (path.find("://")==-1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- path=Globals::get_singleton()->localize_path(local_path.get_base_dir()+"/"+path);
-
- }
-
- //take advantage of the resource loader cache. The resource is cached on it, even if
- RES res=ResourceLoader::load(path,hint);
-
-
- if (res.is_null()) {
-
- WARN_PRINT(String("Couldn't load resource: "+path).ascii().get_data());
- }
-
- r_v=res.get_ref_ptr();
-
- } else if (type=="image") {
-
- if (parser->has_attribute("encoding")) { //there is image data
-
- String encoding=parser->get_attribute_value("encoding");
-
- if (encoding=="raw") {
-
- //raw image (bytes)
-
- XML_FAIL( !parser->has_attribute("width"), "missing attribute in raw encoding: 'width'.");
- XML_FAIL( !parser->has_attribute("height"), "missing attribute in raw encoding: 'height'.");
- XML_FAIL( !parser->has_attribute("format"), "missing attribute in raw encoding: 'format'.");
-
- String format = parser->get_attribute_value("format");
- String width = parser->get_attribute_value("width");
- String height = parser->get_attribute_value("height");
-
- Image::Format imgformat;
- int chans=0;
- int pal=0;
-
- if (format=="grayscale") {
- imgformat=Image::FORMAT_GRAYSCALE;
- chans=1;
- } else if (format=="intensity") {
- imgformat=Image::FORMAT_INTENSITY;
- chans=1;
- } else if (format=="grayscale_alpha") {
- imgformat=Image::FORMAT_GRAYSCALE_ALPHA;
- chans=2;
- } else if (format=="rgb") {
- imgformat=Image::FORMAT_RGB;
- chans=3;
- } else if (format=="rgba") {
- imgformat=Image::FORMAT_RGBA;
- chans=4;
- } else if (format=="indexed") {
- imgformat=Image::FORMAT_INDEXED;
- chans=1;
- pal=256*3;
- } else if (format=="indexed_alpha") {
- imgformat=Image::FORMAT_INDEXED_ALPHA;
- chans=1;
- pal=256*4;
- } else {
-
- XML_FAIL(true, "invalid format for image: "+format);
-
- }
-
- XML_FAIL( chans==0, "invalid number of color channels in image (0).");
-
- int w=width.to_int();
- int h=height.to_int();
-
- if (w == 0 && w == 0) { //epmty, don't even bother
- //r_v = Image(w, h, imgformat);
- r_v=Image();
- return OK;
- } else {
-
- //decode hexa
-
- DVector<uint8_t> pixels;
- pixels.resize(chans*w*h+pal);
- int pixels_size=pixels.size();
- XML_FAIL( pixels_size==0, "corrupt");
-
- ERR_FAIL_COND_V(pixels_size==0,ERR_FILE_CORRUPT);
- DVector<uint8_t>::Write wr=pixels.write();
- uint8_t *bytes=wr.ptr();
-
- XML_FAIL( parser->read()!=OK, "error reading" );
- XML_FAIL( parser->get_node_type()!=XMLParser::NODE_TEXT, "expected text!");
-
- String text = parser->get_node_data().strip_edges();
- XML_FAIL( text.length()/2 != pixels_size, "unexpected image data size" );
-
- for(int i=0;i<pixels_size*2;i++) {
-
- uint8_t byte;
- CharType c=text[i];
-
- if ( (c>='0' && c<='9') || (c>='A' && c<='F') || (c>='a' && c<='f') ) {
-
- if (i&1) {
-
- byte|=HEX2CHR(c);
- bytes[i>>1]=byte;
- } else {
-
- byte=HEX2CHR(c)<<4;
- }
-
-
- }
- }
-
- wr=DVector<uint8_t>::Write();
- r_v=Image(w,h,imgformat,pixels);
- }
- }
-
- } else {
- r_v=Image(); // empty image, since no encoding defined
- }
-
- } else if (type=="raw_array") {
-
- XML_FAIL( !parser->has_attribute("len"), "array missing 'len' attribute");
-
- int len=parser->get_attribute_value("len").to_int();
- if (len>0) {
-
- XML_FAIL( parser->read()!=OK, "error reading" );
- XML_FAIL( parser->get_node_type()!=XMLParser::NODE_TEXT, "expected text!");
- String text = parser->get_node_data();
-
- XML_FAIL( text.length() != len*2, "raw array length mismatch" );
-
- DVector<uint8_t> bytes;
- bytes.resize(len);
- DVector<uint8_t>::Write w=bytes.write();
- uint8_t *bytesptr=w.ptr();
-
-
- for(int i=0;i<len*2;i++) {
-
- uint8_t byte;
- CharType c=text[i];
-
- if ( (c>='0' && c<='9') || (c>='A' && c<='F') || (c>='a' && c<='f') ) {
-
- if (i&1) {
-
- byte|=HEX2CHR(c);
- bytesptr[i>>1]=byte;
- } else {
-
- byte=HEX2CHR(c)<<4;
- }
- }
- }
-
- w=DVector<uint8_t>::Write();
- r_v=bytes;
- }
-
- } else if (type=="int_array") {
-
- int len=parser->get_attribute_value("len").to_int();
-
- if (len>0) {
-
- XML_FAIL( parser->read()!=OK, "error reading" );
- XML_FAIL( parser->get_node_type()!=XMLParser::NODE_TEXT, "expected text!");
- String text = parser->get_node_data();
-
- const CharType *c=text.c_str();
- DVector<int> varray;
- varray.resize(len);
- DVector<int>::Write w = varray.write();
-
- int idx=0;
- const CharType *from=c-1;
-
- while(*c) {
-
- bool ischar = (*c >='0' && *c<='9') || *c=='+' || *c=='-';
- if (!ischar) {
-
- if (int64_t(c-from)>1) {
-
- int i = String::to_int(from+1,int64_t(c-from));
- w[idx++]=i;
- }
-
- from=c;
- } else {
-
- XML_FAIL( idx >= len, "array too big");
- }
-
- c++;
- }
-
- XML_FAIL( idx != len, "array size mismatch");
-
- w = varray.write();
- r_v=varray;
- }
-
-
-
- } else if (type=="real_array") {
-
- int len=parser->get_attribute_value("len").to_int();
-
- if (len>0) {
-
- XML_FAIL( parser->read()!=OK, "error reading" );
- XML_FAIL( parser->get_node_type()!=XMLParser::NODE_TEXT, "expected text!");
- String text = parser->get_node_data();
-
- const CharType *c=text.c_str();
- DVector<real_t> varray;
- varray.resize(len);
- DVector<real_t>::Write w = varray.write();
-
- int idx=0;
- const CharType *from=c-1;
-
- while(*c) {
-
- bool ischar = IS_FLOAT_CHAR((*c));
- if (!ischar) {
-
- if (int64_t(c-from)>1) {
-
- real_t f = String::to_double(from+1,int64_t(c-from));
- w[idx++]=f;
- }
-
- from=c;
- } else {
-
- XML_FAIL( idx >= len, "array too big");
- }
-
- c++;
- }
-
- XML_FAIL( idx != len, "array size mismatch");
-
- w = varray.write();
- r_v=varray;
- }
-
- } else if (type=="string_array") {
-
-
- // this is invalid xml, and will have to be fixed at some point..
-
- int len=parser->get_attribute_value("len").to_int();
-
- if (len>0) {
-
- XML_FAIL( parser->read()!=OK, "error reading" );
- XML_FAIL( parser->get_node_type()!=XMLParser::NODE_TEXT, "expected text!");
- String text = parser->get_node_data();
-
- const CharType *c=text.c_str();
- DVector<String> sarray;
- sarray.resize(len);
- DVector<String>::Write w = sarray.write();
-
-
- bool inside=false;
- const CharType *from=c;
- int idx=0;
-
- while(*c) {
-
- if (inside) {
-
- if (*c == '"') {
- inside=false;
- String s = String(from,int64_t(c-from));
- w[idx]=s;
- idx++;
- }
- } else {
-
- if (*c == '"') {
- inside=true;
- from=c+1;
- XML_FAIL( idx>=len, "string array is too big!!: "+name);
- }
- }
-
- c++;
- }
-
- XML_FAIL( inside, "unterminated string array: "+name);
- XML_FAIL( len != idx, "string array size mismatch: "+name);
-
- w = DVector<String>::Write();
-
- r_v=sarray;
-
- }
- } else if (type=="vector3_array") {
-
- int len=parser->get_attribute_value("len").to_int();
-
- if (len>0) {
-
- XML_FAIL( parser->read()!=OK, "error reading" );
- XML_FAIL( parser->get_node_type()!=XMLParser::NODE_TEXT, "expected text!");
- String text = parser->get_node_data();
-
- const CharType *c=text.c_str();
- DVector<Vector3> varray;
- varray.resize(len);
- DVector<Vector3>::Write w = varray.write();
-
- int idx=0;
- int sidx=0;
- Vector3 v;
- const CharType *from=c-1;
-
- while(*c) {
-
- bool ischar = IS_FLOAT_CHAR((*c));
- if (!ischar) {
-
- if (int64_t(c-from)>1) {
-
- real_t f = String::to_double(from+1,int64_t(c-from));
- v[sidx++]=f;
- if (sidx==3) {
- w[idx++]=v;
- sidx=0;
-
- }
- }
-
- from=c;
- } else {
-
- XML_FAIL( idx >= len, "array too big");
- }
-
- c++;
- }
-
- XML_FAIL( idx != len, "array size mismatch");
-
- w = varray.write();
- r_v=varray;
- }
-
- } else if (type=="color_array") {
-
- int len=parser->get_attribute_value("len").to_int();
-
- if (len>0) {
-
- XML_FAIL( parser->read()!=OK, "error reading" );
- XML_FAIL( parser->get_node_type()!=XMLParser::NODE_TEXT, "expected text!");
- String text = parser->get_node_data();
-
- const CharType *c=text.c_str();
- DVector<Color> carray;
- carray.resize(len);
- DVector<Color>::Write w = carray.write();
-
- int idx=0;
- int sidx=0;
- Color v;
- const CharType *from=c-1;
-
- while(*c) {
-
- bool ischar = IS_FLOAT_CHAR((*c));
- if (!ischar) {
-
- if (int64_t(c-from)>1) {
-
- real_t f = String::to_double(from+1,int64_t(c-from));
- v[sidx++]=f;
- if (sidx==4) {
- w[idx++]=v;
- sidx=0;
-
- }
- }
-
- from=c;
- } else {
-
- XML_FAIL( idx >= len, "array too big");
- }
-
- c++;
- }
-
- XML_FAIL( idx != len, "array size mismatch");
-
- w = carray.write();
- r_v=carray;
- }
- } else {
- // simple string parsing code
- XML_FAIL( parser->read()!=OK, "can't read data" );
-
- String data=parser->get_node_data();
- data=data.strip_edges();
-
- if (type=="nil") {
- // uh do nothing
-
- } else if (type=="bool") {
- // uh do nothing
- if (data.nocasecmp_to("true")==0 || data.to_int()!=0)
- r_v=true;
- else
- r_v=false;
-
- } else if (type=="int") {
-
- r_v=data.to_int();
- } else if (type=="real") {
-
- r_v=data.to_double();
- } else if (type=="string") {
-
- String str=data;
- str=str.substr(1,str.length()-2);
- r_v=str;
- } else if (type=="vector3") {
-
- r_v=Vector3(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double()
- );
-
- } else if (type=="vector2") {
-
-
- r_v=Vector2(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double()
- );
-
- } else if (type=="plane") {
-
- r_v=Plane(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- );
-
- } else if (type=="quaternion") {
-
- r_v=Quat(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- );
-
- } else if (type=="rect2") {
-
- r_v=Rect2(
- Vector2(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double()
- ),
- Vector2(
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- )
- );
-
-
- } else if (type=="aabb") {
-
- r_v=AABB(
- Vector3(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double()
- ),
- Vector3(
- data.get_slice(",",3).to_double(),
- data.get_slice(",",4).to_double(),
- data.get_slice(",",5).to_double()
- )
- );
-
-
- } else if (type=="matrix3") {
-
- Matrix3 m3;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
- m3.elements[i][j]=data.get_slice(",",i*3+j).to_double();
- }
- }
- r_v=m3;
-
- } else if (type=="transform") {
-
- Transform tr;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
- tr.basis.elements[i][j]=data.get_slice(",",i*3+j).to_double();
- }
-
- }
- tr.origin=Vector3(
- data.get_slice(",",9).to_double(),
- data.get_slice(",",10).to_double(),
- data.get_slice(",",11).to_double()
- );
- r_v=tr;
-
- } else if (type=="color") {
-
- r_v=Color(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- );
-
- } else if (type=="node_path") {
-
- String str=data;
- str=str.substr(1,str.length()-2);
- r_v=NodePath( str );
-
- } else if (type=="input_event") {
-
- // ?
- } else {
-
- XML_FAIL(true,"unrecognized property tag: "+type);
- }
- }
-
- _close_tag(type);
-
- return OK;
-}
-
-
-
-
-Error ObjectFormatLoaderXML::_close_tag(const String& p_tag) {
-
- int c=1;
-
- while(parser->read()==OK) {
-
-
- if (parser->get_node_type()==XMLParser::NODE_ELEMENT && parser->get_node_name()==p_tag) {
- c++;
- } else if (parser->get_node_type()==XMLParser::NODE_ELEMENT_END && parser->get_node_name()==p_tag) {
- c--;
-
- if (c==0)
- return OK;
- }
-
- }
-
- return ERR_FILE_CORRUPT;
-}
-
-Error ObjectFormatLoaderXML::load(Object **p_object,Variant &p_meta) {
-
- *p_object=NULL;
- p_meta=Variant();
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type()==XMLParser::NODE_ELEMENT) {
-
- String name = parser->get_node_name();
-
-
- XML_FAIL( !parser->has_attribute("type"), "'type' attribute missing." );
- String type = parser->get_attribute_value("type");
-
-
- Object *obj=NULL;
- Ref<Resource> resource;
- if (name=="resource") {
-
- XML_FAIL( !parser->has_attribute("path"), "'path' attribute missing." );
- String path = parser->get_attribute_value("path");
-
- XML_FAIL(!path.begins_with("local://"),"path does not begin with 'local://'");
-
-
- path=path.replace("local://",local_path+"::");
-
- if (ResourceCache::has(path)) {
- Error err = _close_tag(name);
- XML_FAIL( err, "error skipping resource.");
- continue; //it's a resource, and it's already loaded
-
- }
-
- obj = ObjectTypeDB::instance(type);
- XML_FAIL(!obj,"couldn't instance object of type: '"+type+"'");
-
- Resource *r = obj->cast_to<Resource>();
- XML_FAIL(!obj,"object isn't of type Resource: '"+type+"'");
-
- resource = RES( r );
- r->set_path(path);
-
-
- } else if (name=="object") {
-
-
- if (ObjectTypeDB::can_instance(type)) {
- obj = ObjectTypeDB::instance(type);
- XML_FAIL(!obj,"couldn't instance object of type: '"+type+"'");
- } else {
-
- _close_tag(name);
- return ERR_SKIP;
- };
- } else {
- XML_FAIL(true,"Unknown main tag: "+parser->get_node_name());
- }
-
- //load properties
-
- while (parser->read()==OK) {
-
- if (parser->get_node_type()==XMLParser::NODE_ELEMENT_END && parser->get_node_name()==name)
- break;
- else if (parser->get_node_type()==XMLParser::NODE_ELEMENT) {
-
- String name;
- Variant v;
- Error err;
- err = _parse_property(v,name);
- XML_FAIL(err,"Error parsing property: "+name);
-
- if (resource.is_null() && name=="__xml_meta__") {
-
- p_meta=v;
- continue;
- } else {
-
- XML_FAIL( !obj, "Normal property found in meta object");
-
- }
-
- obj->set(name,v);
-
-
- }
- }
-
-
- if (!obj) {
- *p_object=NULL;
- return OK; // it was a meta object
- }
-
- if (resource.is_null()) {
- //regular object
- *p_object=obj;
- return OK;
- } else {
-
- resource_cache.push_back(resource); //keep it in mem until finished loading and load next
- }
-
-
- } else if (parser->get_node_type()==XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="object_file")
- return ERR_FILE_EOF;
- }
-
- return OK; //never reach anyway
-}
-
-ObjectFormatLoaderXML* ObjectFormatLoaderInstancerXML::instance(const String& p_file,const String& p_magic) {
-
- Ref<XMLParser> parser = memnew( XMLParser );
-
- Error err = parser->open(p_file);
- ERR_FAIL_COND_V(err,NULL);
-
- ObjectFormatLoaderXML *loader = memnew( ObjectFormatLoaderXML );
-
- loader->parser=parser;
- loader->local_path = Globals::get_singleton()->localize_path(p_file);
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type()==XMLParser::NODE_ELEMENT && parser->get_node_name()=="object_file") {
-
- ERR_FAIL_COND_V( parser->is_empty(), NULL );
-
- String version = parser->get_attribute_value_safe("version");
- String magic = parser->get_attribute_value_safe("MAGIC");
-
- if (version.get_slice_count(".")!=2) {
-
- ERR_EXPLAIN("Invalid Version String '"+version+"'' in file: "+p_file);
- ERR_FAIL_V(NULL);
- }
-
- int major = version.get_slice(".",0).to_int();
- int minor = version.get_slice(".",1).to_int();
-
- if (major>VERSION_MAJOR || (major==VERSION_MAJOR && minor>VERSION_MINOR)) {
-
- ERR_EXPLAIN("File Format '"+version+"' is too new! Please upgrade to a a new engine version: "+p_file);
- ERR_FAIL_V(NULL);
-
- }
-
- return loader;
- }
-
- }
-
- ERR_EXPLAIN("No data found in file!");
- ERR_FAIL_V(NULL);
-}
-
-void ObjectFormatLoaderInstancerXML::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("xml");
-}
-
-
-
-#else
-
-ObjectFormatLoaderXML::Tag* ObjectFormatLoaderXML::parse_tag(bool *r_exit) {
-
-
- while(get_char()!='<' && !f->eof_reached()) {}
- if (f->eof_reached())
- return NULL;
-
- Tag tag;
- bool exit=false;
- if (r_exit)
- *r_exit=false;
-
- bool complete=false;
- while(!f->eof_reached()) {
-
- CharType c=get_char();
- if (c<33 && tag.name.length() && !exit) {
- break;
- } else if (c=='>') {
- complete=true;
- break;
- } else if (c=='/') {
- exit=true;
- } else {
- tag.name+=c;
- }
- }
-
- if (f->eof_reached())
- return NULL;
-
- if (exit) {
- if (!tag_stack.size()) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Unmatched exit tag </"+tag.name+">");
- ERR_FAIL_COND_V(!tag_stack.size(),NULL);
- }
-
- if (tag_stack.back()->get().name!=tag.name) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Mismatched exit tag. Got </"+tag.name+">, expected </"+tag_stack.back()->get().name+">");
- ERR_FAIL_COND_V(tag_stack.back()->get().name!=tag.name,NULL);
- }
-
- if (!complete) {
- while(get_char()!='>' && !f->eof_reached()) {}
- if (f->eof_reached())
- return NULL;
- }
-
- if (r_exit)
- *r_exit=true;
-
- tag_stack.pop_back();
- return NULL;
-
- }
-
- if (!complete) {
- String name;
- String value;
- bool reading_value=false;
-
- while(!f->eof_reached()) {
-
- CharType c=get_char();
- if (c=='>') {
- if (value.length()) {
-
- tag.args[name]=value;
- }
- break;
-
- } else if ( ((!reading_value && (c<33)) || c=='=' || c=='"') && tag.name.length()) {
-
- if (!reading_value && name.length()) {
-
- reading_value=true;
- } else if (reading_value && value.length()) {
-
- tag.args[name]=value;
- name="";
- value="";
- reading_value=false;
- }
-
- } else if (reading_value) {
-
- value+=c;
- } else {
-
- name+=c;
- }
- }
-
- if (f->eof_reached())
- return NULL;
- }
-
- tag_stack.push_back(tag);
-
- return &tag_stack.back()->get();
-}
-
-
-Error ObjectFormatLoaderXML::close_tag(const String& p_name) {
-
- int level=0;
- bool inside_tag=false;
-
- while(true) {
-
- if (f->eof_reached()) {
-
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": EOF found while attempting to find </"+p_name+">");
- ERR_FAIL_COND_V( f->eof_reached(), ERR_FILE_CORRUPT );
- }
-
- uint8_t c = get_char();
-
- if (c == '<') {
-
- if (inside_tag) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Malformed XML. Already inside Tag.");
- ERR_FAIL_COND_V(inside_tag,ERR_FILE_CORRUPT);
- }
- inside_tag=true;
- c = get_char();
- if (c == '/') {
-
- --level;
- } else {
-
- ++level;
- };
- } else if (c == '>') {
-
- if (!inside_tag) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Malformed XML. Already outside Tag");
- ERR_FAIL_COND_V(!inside_tag,ERR_FILE_CORRUPT);
- }
- inside_tag=false;
- if (level == -1) {
- tag_stack.pop_back();
- return OK;
- };
- };
- }
-
- return OK;
-}
-
-void ObjectFormatLoaderXML::unquote(String& p_str) {
-
- p_str=p_str.strip_edges();
- p_str=p_str.replace("\"","");
- p_str=p_str.replace("&gt;","<");
- p_str=p_str.replace("&lt;",">");
- p_str=p_str.replace("&apos;","'");
- p_str=p_str.replace("&quot;","\"");
- for (int i=1;i<32;i++) {
-
- char chr[2]={i,0};
- p_str=p_str.replace("&#"+String::num(i)+";",chr);
- }
- p_str=p_str.replace("&amp;","&");
-
- //p_str.parse_utf8( p_str.ascii(true).get_data() );
-
-}
-
-Error ObjectFormatLoaderXML::goto_end_of_tag() {
-
- uint8_t c;
- while(true) {
-
- c=get_char();
- if (c=='>') //closetag
- break;
- if (f->eof_reached()) {
-
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": EOF found while attempting to find close tag.");
- ERR_FAIL_COND_V( f->eof_reached(), ERR_FILE_CORRUPT );
- }
-
- }
- tag_stack.pop_back();
-
- return OK;
-}
-
-
-Error ObjectFormatLoaderXML::parse_property_data(String &r_data) {
-
- r_data="";
- CharString cs;
- while(true) {
-
- CharType c=get_char();
- if (c=='<')
- break;
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
- cs.push_back(c);
- }
-
- cs.push_back(0);
-
- r_data.parse_utf8(cs.get_data());
-
- while(get_char()!='>' && !f->eof_reached()) {}
- if (f->eof_reached()) {
-
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Malformed XML.");
- ERR_FAIL_COND_V( f->eof_reached(), ERR_FILE_CORRUPT );
- }
-
- r_data=r_data.strip_edges();
- tag_stack.pop_back();
-
- return OK;
-}
-
-
-Error ObjectFormatLoaderXML::_parse_array_element(Vector<char> &buff,bool p_number_only,FileAccess *f,bool *end) {
-
- if (buff.empty())
- buff.resize(32); // optimize
-
- int buff_max=buff.size();
- int buff_size=0;
- *end=false;
- char *buffptr=&buff[0];
- bool found=false;
- bool quoted=false;
-
- while(true) {
-
- char c=get_char();
-
- if (c==0) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": File corrupt (zero found).");
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- } else if (c=='"') {
- quoted=!quoted;
- } else if ((!quoted && ((p_number_only && c<33) || c==',')) || c=='<') {
-
-
- if (c=='<') {
- *end=true;
- break;
- }
- if (c<32 && f->eof_reached()) {
- *end=true;
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": File corrupt (unexpected EOF).");
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- if (found)
- break;
-
- } else {
-
- found=true;
- if (buff_size>=buff_max) {
-
- buff_max++;
- buff.resize(buff_max);
-
- }
-
- buffptr[buff_size]=c;
- buff_size++;
- }
- }
-
- if (buff_size>=buff_max) {
-
- buff_max++;
- buff.resize(buff_max);
-
- }
-
- buff[buff_size]=0;
- buff_size++;
-
- return OK;
-}
-
-Error ObjectFormatLoaderXML::parse_property(Variant& r_v, String &r_name) {
-
- bool exit;
- Tag *tag = parse_tag(&exit);
-
- if (!tag) {
- if (exit) // shouldn't have exited
- return ERR_FILE_EOF;
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": File corrupt (No Property Tag).");
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- r_v=Variant();
- r_name="";
-
-
- //ERR_FAIL_COND_V(tag->name!="property",ERR_FILE_CORRUPT);
- //ERR_FAIL_COND_V(!tag->args.has("name"),ERR_FILE_CORRUPT);
-// ERR_FAIL_COND_V(!tag->args.has("type"),ERR_FILE_CORRUPT);
-
- //String name=tag->args["name"];
- //ERR_FAIL_COND_V(name=="",ERR_FILE_CORRUPT);
- String type=tag->name;
- String name=tag->args["name"];
-
- if (type=="") {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": 'type' field is empty.");
- ERR_FAIL_COND_V(type=="",ERR_FILE_CORRUPT);
- }
-
- if (type=="dictionary") {
-
- Dictionary d;
-
- while(true) {
-
- Error err;
- String tagname;
- Variant key;
-
- int dictline = get_current_line();
-
-
- err=parse_property(key,tagname);
-
- if (err && err!=ERR_FILE_EOF) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error parsing dictionary: "+name+" (from line "+itos(dictline)+")");
- ERR_FAIL_COND_V(err && err!=ERR_FILE_EOF,err);
- }
- //ERR_FAIL_COND_V(tagname!="key",ERR_FILE_CORRUPT);
- if (err)
- break;
- Variant value;
- err=parse_property(value,tagname);
- if (err) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error parsing dictionary: "+name+" (from line "+itos(dictline)+")");
- }
-
- ERR_FAIL_COND_V(err,err);
- //ERR_FAIL_COND_V(tagname!="value",ERR_FILE_CORRUPT);
-
- d[key]=value;
- }
-
-
- //err=parse_property_data(name); // skip the rest
- //ERR_FAIL_COND_V(err,err);
-
- r_name=name;
- r_v=d;
- return OK;
-
- } else if (type=="array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
-
-
- int len=tag->args["len"].to_int();
-
- Array array;
- array.resize(len);
-
- Error err;
- Variant v;
- String tagname;
- int idx=0;
- while( (err=parse_property(v,tagname))==OK ) {
-
- ERR_CONTINUE( idx <0 || idx >=len );
-
- array.set(idx,v);
- idx++;
- }
-
- if (idx!=len) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error loading array (size mismatch): "+name);
- ERR_FAIL_COND_V(idx!=len,err);
- }
-
- if (err!=ERR_FILE_EOF) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error loading array: "+name);
- ERR_FAIL_COND_V(err!=ERR_FILE_EOF,err);
- }
-
- //err=parse_property_data(name); // skip the rest
- //ERR_FAIL_COND_V(err,err);
-
- r_name=name;
- r_v=array;
- return OK;
-
- } else if (type=="resource") {
-
- if (tag->args.has("path")) {
-
- String path=tag->args["path"];
- String hint;
- if (tag->args.has("resource_type"))
- hint=tag->args["resource_type"];
-
- if (path.begins_with("local://"))
- path=path.replace("local://",local_path+"::");
- else if (path.find("://")==-1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- path=Globals::get_singleton()->localize_path(local_path.get_base_dir()+"/"+path);
-
- }
-
- //take advantage of the resource loader cache. The resource is cached on it, even if
- RES res=ResourceLoader::load(path,hint);
-
-
- if (res.is_null()) {
-
- WARN_PRINT(String("Couldn't load resource: "+path).ascii().get_data());
- }
-
- r_v=res.get_ref_ptr();
- }
-
-
-
- Error err=goto_end_of_tag();
- if (err) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error closing <resource> tag.");
- ERR_FAIL_COND_V(err,err);
- }
-
-
- r_name=name;
-
- return OK;
-
- } else if (type=="image") {
-
- if (!tag->args.has("encoding")) {
- //empty image
- r_v=Image();
- String sdfsdfg;
- Error err=parse_property_data(sdfsdfg);
- return OK;
- }
-
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Image missing 'encoding' field.");
- ERR_FAIL_COND_V( !tag->args.has("encoding"), ERR_FILE_CORRUPT );
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Image missing 'width' field.");
- ERR_FAIL_COND_V( !tag->args.has("width"), ERR_FILE_CORRUPT );
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Image missing 'height' field.");
- ERR_FAIL_COND_V( !tag->args.has("height"), ERR_FILE_CORRUPT );
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Image missing 'format' field.");
- ERR_FAIL_COND_V( !tag->args.has("format"), ERR_FILE_CORRUPT );
-
- String encoding=tag->args["encoding"];
-
- if (encoding=="raw") {
- String width=tag->args["width"];
- String height=tag->args["height"];
- String format=tag->args["format"];
- int mipmaps=tag->args.has("mipmaps")?int(tag->args["mipmaps"].to_int()):int(0);
- int custom_size = tag->args.has("custom_size")?int(tag->args["custom_size"].to_int()):int(0);
-
- r_name=name;
-
- Image::Format imgformat;
-
-
- if (format=="grayscale") {
- imgformat=Image::FORMAT_GRAYSCALE;
- } else if (format=="intensity") {
- imgformat=Image::FORMAT_INTENSITY;
- } else if (format=="grayscale_alpha") {
- imgformat=Image::FORMAT_GRAYSCALE_ALPHA;
- } else if (format=="rgb") {
- imgformat=Image::FORMAT_RGB;
- } else if (format=="rgba") {
- imgformat=Image::FORMAT_RGBA;
- } else if (format=="indexed") {
- imgformat=Image::FORMAT_INDEXED;
- } else if (format=="indexed_alpha") {
- imgformat=Image::FORMAT_INDEXED_ALPHA;
- } else if (format=="bc1") {
- imgformat=Image::FORMAT_BC1;
- } else if (format=="bc2") {
- imgformat=Image::FORMAT_BC2;
- } else if (format=="bc3") {
- imgformat=Image::FORMAT_BC3;
- } else if (format=="bc4") {
- imgformat=Image::FORMAT_BC4;
- } else if (format=="bc5") {
- imgformat=Image::FORMAT_BC5;
- } else if (format=="custom") {
- imgformat=Image::FORMAT_CUSTOM;
- } else {
-
- ERR_FAIL_V( ERR_FILE_CORRUPT );
- }
-
-
- int datasize;
- int w=width.to_int();
- int h=height.to_int();
-
- if (w == 0 && w == 0) {
- //r_v = Image(w, h, imgformat);
- r_v=Image();
- String sdfsdfg;
- Error err=parse_property_data(sdfsdfg);
- return OK;
- };
-
- if (imgformat==Image::FORMAT_CUSTOM) {
-
- datasize=custom_size;
- } else {
-
- datasize = Image::get_image_data_size(h,w,imgformat,mipmaps);
- }
-
- if (datasize==0) {
- //r_v = Image(w, h, imgformat);
- r_v=Image();
- String sdfsdfg;
- Error err=parse_property_data(sdfsdfg);
- return OK;
- };
-
- DVector<uint8_t> pixels;
- pixels.resize(datasize);
- DVector<uint8_t>::Write wb = pixels.write();
-
- int idx=0;
- uint8_t byte;
- while( idx<datasize*2) {
-
- CharType c=get_char();
-
- ERR_FAIL_COND_V(c=='<',ERR_FILE_CORRUPT);
-
- if ( (c>='0' && c<='9') || (c>='A' && c<='F') || (c>='a' && c<='f') ) {
-
- if (idx&1) {
-
- byte|=HEX2CHR(c);
- wb[idx>>1]=byte;
- } else {
-
- byte=HEX2CHR(c)<<4;
- }
-
- idx++;
- }
-
- }
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
- wb=DVector<uint8_t>::Write();
-
- r_v=Image(w,h,mipmaps,imgformat,pixels);
- String sdfsdfg;
- Error err=parse_property_data(sdfsdfg);
- ERR_FAIL_COND_V(err,err);
-
- return OK;
- }
-
- ERR_FAIL_V(ERR_FILE_CORRUPT);
-
- } else if (type=="raw_array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": RawArray missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
- int len=tag->args["len"].to_int();
-
- DVector<uint8_t> bytes;
- bytes.resize(len);
- DVector<uint8_t>::Write w=bytes.write();
- uint8_t *bytesptr=w.ptr();
- int idx=0;
- uint8_t byte;
- while( idx<len*2) {
-
- CharType c=get_char();
-
- if (idx&1) {
-
- byte|=HEX2CHR(c);
- bytesptr[idx>>1]=byte;
- } else {
-
- byte=HEX2CHR(c)<<4;
- }
-
- idx++;
- }
-
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
- w=DVector<uint8_t>::Write();
- r_v=bytes;
- String sdfsdfg;
- Error err=parse_property_data(sdfsdfg);
- ERR_FAIL_COND_V(err,err);
- r_name=name;
-
- return OK;
-
- } else if (type=="int_array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
- int len=tag->args["len"].to_int();
-
- DVector<int> ints;
- ints.resize(len);
- DVector<int>::Write w=ints.write();
- int *intsptr=w.ptr();
- int idx=0;
- String str;
-#if 0
- while( idx<len ) {
-
-
- CharType c=get_char();
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
- if (c<33 || c==',' || c=='<') {
-
- if (str.length()) {
-
- intsptr[idx]=str.to_int();
- str="";
- idx++;
- }
-
- if (c=='<') {
-
- while(get_char()!='>' && !f->eof_reached()) {}
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
- break;
- }
-
- } else {
-
- str+=c;
- }
- }
-
-#else
-
- Vector<char> tmpdata;
-
- while( idx<len ) {
-
- bool end=false;
- Error err = _parse_array_element(tmpdata,true,f,&end);
- ERR_FAIL_COND_V(err,err);
-
- intsptr[idx]=String::to_int(&tmpdata[0]);
- idx++;
- if (end)
- break;
-
- }
-
-#endif
- w=DVector<int>::Write();
-
- r_v=ints;
- Error err=goto_end_of_tag();
- ERR_FAIL_COND_V(err,err);
- r_name=name;
-
- return OK;
- } else if (type=="real_array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
- int len=tag->args["len"].to_int();;
-
- DVector<real_t> reals;
- reals.resize(len);
- DVector<real_t>::Write w=reals.write();
- real_t *realsptr=w.ptr();
- int idx=0;
- String str;
-
-
-#if 0
- while( idx<len ) {
-
-
- CharType c=get_char();
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
-
- if (c<33 || c==',' || c=='<') {
-
- if (str.length()) {
-
- realsptr[idx]=str.to_double();
- str="";
- idx++;
- }
-
- if (c=='<') {
-
- while(get_char()!='>' && !f->eof_reached()) {}
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
- break;
- }
-
- } else {
-
- str+=c;
- }
- }
-
-#else
-
-
-
- Vector<char> tmpdata;
-
- while( idx<len ) {
-
- bool end=false;
- Error err = _parse_array_element(tmpdata,true,f,&end);
- ERR_FAIL_COND_V(err,err);
-
- realsptr[idx]=String::to_double(&tmpdata[0]);
- idx++;
-
- if (end)
- break;
- }
-
-#endif
-
- w=DVector<real_t>::Write();
- r_v=reals;
-
- Error err=goto_end_of_tag();
- ERR_FAIL_COND_V(err,err);
- r_name=name;
-
- return OK;
- } else if (type=="string_array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
- int len=tag->args["len"].to_int();
-
- DVector<String> strings;
- strings.resize(len);
- DVector<String>::Write w=strings.write();
- String *stringsptr=w.ptr();
- int idx=0;
- String str;
-
- bool inside_str=false;
- CharString cs;
- while( idx<len ) {
-
-
- CharType c=get_char();
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
-
- if (c=='"') {
- if (inside_str) {
-
- cs.push_back(0);
- String str;
- str.parse_utf8(cs.get_data());
- unquote(str);
- stringsptr[idx]=str;
- cs.clear();
- idx++;
- inside_str=false;
- } else {
- inside_str=true;
- }
- } else if (c=='<') {
-
- while(get_char()!='>' && !f->eof_reached()) {}
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
- break;
-
-
- } else if (inside_str){
-
- cs.push_back(c);
- }
- }
- w=DVector<String>::Write();
- r_v=strings;
- String sdfsdfg;
- Error err=parse_property_data(sdfsdfg);
- ERR_FAIL_COND_V(err,err);
-
- r_name=name;
-
- return OK;
- } else if (type=="vector3_array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
- int len=tag->args["len"].to_int();;
-
- DVector<Vector3> vectors;
- vectors.resize(len);
- DVector<Vector3>::Write w=vectors.write();
- Vector3 *vectorsptr=w.ptr();
- int idx=0;
- int subidx=0;
- Vector3 auxvec;
- String str;
-
-// uint64_t tbegin = OS::get_singleton()->get_ticks_usec();
-#if 0
- while( idx<len ) {
-
-
- CharType c=get_char();
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
-
- if (c<33 || c==',' || c=='<') {
-
- if (str.length()) {
-
- auxvec[subidx]=str.to_double();
- subidx++;
- str="";
- if (subidx==3) {
- vectorsptr[idx]=auxvec;
-
- idx++;
- subidx=0;
- }
- }
-
- if (c=='<') {
-
- while(get_char()!='>' && !f->eof_reached()) {}
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
- break;
- }
-
- } else {
-
- str+=c;
- }
- }
-#else
-
- Vector<char> tmpdata;
-
- while( idx<len ) {
-
- bool end=false;
- Error err = _parse_array_element(tmpdata,true,f,&end);
- ERR_FAIL_COND_V(err,err);
-
-
- auxvec[subidx]=String::to_double(&tmpdata[0]);
- subidx++;
- if (subidx==3) {
- vectorsptr[idx]=auxvec;
-
- idx++;
- subidx=0;
- }
-
- if (end)
- break;
- }
-
-
-
-#endif
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Premature end of vector3 array");
- ERR_FAIL_COND_V(idx<len,ERR_FILE_CORRUPT);
-// double time_taken = (OS::get_singleton()->get_ticks_usec() - tbegin)/1000000.0;
-
-
- w=DVector<Vector3>::Write();
- r_v=vectors;
- String sdfsdfg;
- Error err=goto_end_of_tag();
- ERR_FAIL_COND_V(err,err);
- r_name=name;
-
- return OK;
-
- } else if (type=="vector2_array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
- int len=tag->args["len"].to_int();;
-
- DVector<Vector2> vectors;
- vectors.resize(len);
- DVector<Vector2>::Write w=vectors.write();
- Vector2 *vectorsptr=w.ptr();
- int idx=0;
- int subidx=0;
- Vector2 auxvec;
- String str;
-
-// uint64_t tbegin = OS::get_singleton()->get_ticks_usec();
-#if 0
- while( idx<len ) {
-
-
- CharType c=get_char();
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
-
- if (c<22 || c==',' || c=='<') {
-
- if (str.length()) {
-
- auxvec[subidx]=str.to_double();
- subidx++;
- str="";
- if (subidx==2) {
- vectorsptr[idx]=auxvec;
-
- idx++;
- subidx=0;
- }
- }
-
- if (c=='<') {
-
- while(get_char()!='>' && !f->eof_reached()) {}
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
- break;
- }
-
- } else {
-
- str+=c;
- }
- }
-#else
-
- Vector<char> tmpdata;
-
- while( idx<len ) {
-
- bool end=false;
- Error err = _parse_array_element(tmpdata,true,f,&end);
- ERR_FAIL_COND_V(err,err);
-
-
- auxvec[subidx]=String::to_double(&tmpdata[0]);
- subidx++;
- if (subidx==2) {
- vectorsptr[idx]=auxvec;
-
- idx++;
- subidx=0;
- }
-
- if (end)
- break;
- }
-
-
-
-#endif
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Premature end of vector2 array");
- ERR_FAIL_COND_V(idx<len,ERR_FILE_CORRUPT);
-// double time_taken = (OS::get_singleton()->get_ticks_usec() - tbegin)/1000000.0;
-
-
- w=DVector<Vector2>::Write();
- r_v=vectors;
- String sdfsdfg;
- Error err=goto_end_of_tag();
- ERR_FAIL_COND_V(err,err);
- r_name=name;
-
- return OK;
-
- } else if (type=="color_array") {
-
- if (!tag->args.has("len")) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
- ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
- }
- int len=tag->args["len"].to_int();;
-
- DVector<Color> colors;
- colors.resize(len);
- DVector<Color>::Write w=colors.write();
- Color *colorsptr=w.ptr();
- int idx=0;
- int subidx=0;
- Color auxcol;
- String str;
-
- while( idx<len ) {
-
-
- CharType c=get_char();
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
-
-
- if (c<33 || c==',' || c=='<') {
-
- if (str.length()) {
-
- auxcol[subidx]=str.to_double();
- subidx++;
- str="";
- if (subidx==4) {
- colorsptr[idx]=auxcol;
- idx++;
- subidx=0;
- }
- }
-
- if (c=='<') {
-
- while(get_char()!='>' && !f->eof_reached()) {}
- ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
- break;
- }
-
- } else {
-
- str+=c;
- }
- }
- w=DVector<Color>::Write();
- r_v=colors;
- String sdfsdfg;
- Error err=parse_property_data(sdfsdfg);
- ERR_FAIL_COND_V(err,err);
- r_name=name;
-
- return OK;
- }
-
-
- String data;
- Error err = parse_property_data(data);
- ERR_FAIL_COND_V(err!=OK,err);
-
- if (type=="nil") {
- // uh do nothing
-
- } else if (type=="bool") {
- // uh do nothing
- if (data.nocasecmp_to("true")==0 || data.to_int()!=0)
- r_v=true;
- else
- r_v=false;
- } else if (type=="int") {
-
- r_v=data.to_int();
- } else if (type=="real") {
-
- r_v=data.to_double();
- } else if (type=="string") {
-
- String str=data;
- unquote(str);
- r_v=str;
- } else if (type=="vector3") {
-
-
- r_v=Vector3(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double()
- );
-
- } else if (type=="vector2") {
-
-
- r_v=Vector2(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double()
- );
-
- } else if (type=="plane") {
-
- r_v=Plane(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- );
-
- } else if (type=="quaternion") {
-
- r_v=Quat(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- );
-
- } else if (type=="rect2") {
-
- r_v=Rect2(
- Vector2(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double()
- ),
- Vector2(
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- )
- );
-
-
- } else if (type=="aabb") {
-
- r_v=AABB(
- Vector3(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double()
- ),
- Vector3(
- data.get_slice(",",3).to_double(),
- data.get_slice(",",4).to_double(),
- data.get_slice(",",5).to_double()
- )
- );
-
- } else if (type=="matrix32") {
-
- Matrix32 m3;
- for (int i=0;i<3;i++) {
- for (int j=0;j<2;j++) {
- m3.elements[i][j]=data.get_slice(",",i*2+j).to_double();
- }
- }
- r_v=m3;
-
- } else if (type=="matrix3") {
-
- Matrix3 m3;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
- m3.elements[i][j]=data.get_slice(",",i*3+j).to_double();
- }
- }
- r_v=m3;
-
- } else if (type=="transform") {
-
- Transform tr;
- for (int i=0;i<3;i++) {
- for (int j=0;j<3;j++) {
- tr.basis.elements[i][j]=data.get_slice(",",i*3+j).to_double();
- }
-
- }
- tr.origin=Vector3(
- data.get_slice(",",9).to_double(),
- data.get_slice(",",10).to_double(),
- data.get_slice(",",11).to_double()
- );
- r_v=tr;
-
- } else if (type=="color") {
-
- r_v=Color(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
- );
-
- } else if (type=="node_path") {
-
- String str=data;
- unquote(str);
- r_v=NodePath( str );
- } else if (type=="input_event") {
-
- // ?
- } else {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Unrecognized tag in file: "+type);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
- r_name=name;
- return OK;
-}
-
-
-Error ObjectFormatLoaderXML::load(Object **p_object,Variant &p_meta) {
-
- *p_object=NULL;
- p_meta=Variant();
-
-
-
- while(true) {
-
-
- bool exit;
- Tag *tag = parse_tag(&exit);
-
-
- if (!tag) {
- if (!exit) // shouldn't have exited
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- *p_object=NULL;
- return ERR_FILE_EOF;
- }
-
- RES resource;
- Object *obj=NULL;
-
- if (tag->name=="resource") {
- //loading resource
-
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <resource> missing 'len' field.");
- ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT);
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <resource> missing 'type' field.");
- ERR_FAIL_COND_V(!tag->args.has("type"),ERR_FILE_CORRUPT);
- String path=tag->args["path"];
-
- if (path.begins_with("local://")) {
- //built-in resource (but really external)
- path=path.replace("local://",local_path+"::");
- }
-
-
- if (ResourceCache::has(path)) {
- Error err = close_tag(tag->name);
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Unable to close <resource> tag.");
- ERR_FAIL_COND_V( err, err );
- continue; //it's a resource, and it's already loaded
-
- }
-
- String type = tag->args["type"];
-
- obj = ObjectTypeDB::instance(type);
- if (!obj) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Object of unrecognized type in file: "+type);
- }
- ERR_FAIL_COND_V(!obj,ERR_FILE_CORRUPT);
-
- Resource *r = obj->cast_to<Resource>();
- if (!r) {
- memdelete(obj); //bye
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Object type in resource field not a resource, type is: "+obj->get_type());
- ERR_FAIL_COND_V(!obj->cast_to<Resource>(),ERR_FILE_CORRUPT);
- }
-
- resource = RES( r );
- r->set_path(path);
-
-
-
- } else if (tag->name=="object") {
-
- if ( tag->args.has("type") ) {
-
- ERR_FAIL_COND_V(!ObjectTypeDB::type_exists(tag->args["type"]), ERR_FILE_CORRUPT);
-
- if (ObjectTypeDB::can_instance(tag->args["type"])) {
- obj = ObjectTypeDB::instance(tag->args["type"]);
- if (!obj) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Object of unrecognized type in file: "+tag->args["type"]);
- }
- ERR_FAIL_COND_V(!obj,ERR_FILE_CORRUPT);
- } else {
-
- close_tag(tag->name);
- return ERR_SKIP;
- };
- } else {
- //otherwise it's a meta object
- }
-
- } else {
-
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Unknown main tag: "+tag->name);
- ERR_FAIL_V( ERR_FILE_CORRUPT );
- }
-
- //load properties
-
- while(true) {
-
- String name;
- Variant v;
- Error err;
- err = parse_property(v,name);
- if (err==ERR_FILE_EOF) //tag closed
- break;
- if (err!=OK) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": XML Parsing aborted.");
- ERR_FAIL_COND_V(err!=OK,ERR_FILE_CORRUPT);
- }
- if (resource.is_null() && name=="__xml_meta__") {
-
- p_meta=v;
- continue;
- } else if (!obj) {
-
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Normal property found in meta object.");
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- obj->set(name,v);
- }
-
- if (!obj) {
- *p_object=NULL;
- return OK; // it was a meta object
- }
-
- if (resource.is_null()) {
-
- //regular object
- *p_object=obj;
- return OK;
- } else {
-
-
- resource_cache.push_back(resource); //keep it in mem until finished loading
- }
-
- // a resource.. continue!
-
- }
-
-
-
- return OK; //never reach anyway
-
-}
-
-int ObjectFormatLoaderXML::get_current_line() const {
-
- return lines;
-}
-
-
-uint8_t ObjectFormatLoaderXML::get_char() const {
-
- uint8_t c = f->get_8();
- if (c=='\n')
- lines++;
- return c;
-
-}
-
-ObjectFormatLoaderXML::~ObjectFormatLoaderXML() {
-
- if (f) {
- if (f->is_open())
- f->close();
- memdelete(f);
- }
-}
-
-
-
-ObjectFormatLoaderXML* ObjectFormatLoaderInstancerXML::instance(const String& p_file,const String& p_magic) {
-
- Error err;
- FileAccess *f=FileAccess::open(p_file,FileAccess::READ,&err);
- if (err!=OK) {
-
- ERR_FAIL_COND_V(err!=OK,NULL);
- }
-
- ObjectFormatLoaderXML *loader = memnew( ObjectFormatLoaderXML );
-
- loader->lines=1;
- loader->f=f;
- loader->local_path = Globals::get_singleton()->localize_path(p_file);
-
- ObjectFormatLoaderXML::Tag *tag = loader->parse_tag();
- if (!tag || tag->name!="?xml" || !tag->args.has("version") || !tag->args.has("encoding") || tag->args["encoding"]!="UTF-8") {
-
- f->close();
- memdelete(loader);
- ERR_EXPLAIN("Not a XML:UTF-8 File: "+p_file);
- ERR_FAIL_V(NULL);
- }
-
- loader->tag_stack.clear();
-
- tag = loader->parse_tag();
-
- if (!tag || tag->name!="object_file" || !tag->args.has("magic") || !tag->args.has("version") || tag->args["magic"]!=p_magic) {
-
- f->close();
- memdelete(loader);
- ERR_EXPLAIN("Unrecognized XML File: "+p_file);
- ERR_FAIL_V(NULL);
- }
-
- String version = tag->args["version"];
- if (version.get_slice_count(".")!=2) {
-
- f->close();
- memdelete(loader);
- ERR_EXPLAIN("Invalid Version String '"+version+"'' in file: "+p_file);
- ERR_FAIL_V(NULL);
- }
-
- int major = version.get_slice(".",0).to_int();
- int minor = version.get_slice(".",1).to_int();
-
- if (major>VERSION_MAJOR || (major==VERSION_MAJOR && minor>VERSION_MINOR)) {
-
- f->close();
- memdelete(loader);
- ERR_EXPLAIN("File Format '"+version+"' is too new! Please upgrade to a a new engine version: "+p_file);
- ERR_FAIL_V(NULL);
-
- }
-
- return loader;
-}
-
-void ObjectFormatLoaderInstancerXML::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("xml");
-}
-
-
-#endif
-#endif
-#endif
diff --git a/core/io/object_format_xml.h b/core/io/object_format_xml.h
deleted file mode 100644
index 1169a1de58..0000000000
--- a/core/io/object_format_xml.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*************************************************************************/
-/* object_format_xml.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 OBJECT_FORMAT_XML_H
-#define OBJECT_FORMAT_XML_H
-
-#ifdef XML_ENABLED
-#ifdef OLD_SCENE_FORMAT_ENABLED
-#include "io/object_loader.h"
-#include "io/object_saver.h"
-#include "os/file_access.h"
-#include "map.h"
-#include "resource.h"
-#include "xml_parser.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class ObjectFormatSaverXML : public ObjectFormatSaver {
-
- String local_path;
-
-
- Ref<OptimizedSaver> optimizer;
-
- bool relative_paths;
- bool bundle_resources;
- bool skip_editor;
- FileAccess *f;
- String magic;
- int depth;
- Map<RES,int> resource_map;
-
- struct SavedObject {
-
- Variant meta;
- String type;
-
-
- struct SavedProperty {
-
- String name;
- Variant value;
- };
-
- List<SavedProperty> properties;
- };
-
- List<RES> saved_resources;
-
- List<SavedObject*> saved_objects;
-
- void enter_tag(const String& p_section,const String& p_args="");
- void exit_tag(const String& p_section);
-
- void _find_resources(const Variant& p_variant);
- void write_property(const String& p_name,const Variant& p_property,bool *r_ok=NULL);
-
-
- void escape(String& p_str);
- void write_tabs(int p_diff=0);
- void write_string(String p_str,bool p_escape=true);
-
-public:
-
- virtual Error save(const Object *p_object,const Variant &p_meta);
-
- ObjectFormatSaverXML(FileAccess *p_file,const String& p_magic,const String& p_local_path,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer);
- ~ObjectFormatSaverXML();
-};
-
-class ObjectFormatSaverInstancerXML : public ObjectFormatSaverInstancer {
-public:
-
- virtual ObjectFormatSaver* instance(const String& p_file,const String& p_magic,uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>());
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
- virtual ~ObjectFormatSaverInstancerXML();
-};
-
-/***********************************/
-/***********************************/
-/***********************************/
-/***********************************/
-
-//#define OPTIMIZED_XML_LOADER
-
-#ifdef OPTIMIZED_XML_LOADER
-
-class ObjectFormatLoaderXML : public ObjectFormatLoader {
-
- Ref<XMLParser> parser;
- String local_path;
-
- Error _close_tag(const String& p_tag);
- Error _parse_property(Variant& r_property,String& r_name);
-
-friend class ObjectFormatLoaderInstancerXML;
-
- List<RES> resource_cache;
-public:
-
-
- virtual Error load(Object **p_object,Variant &p_meta);
-
-
-};
-
-class ObjectFormatLoaderInstancerXML : public ObjectFormatLoaderInstancer {
-public:
-
- virtual ObjectFormatLoaderXML* instance(const String& p_file,const String& p_magic);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
-};
-
-#else
-
-
-class ObjectFormatLoaderXML : public ObjectFormatLoader {
-
- String local_path;
-
- FileAccess *f;
-
- struct Tag {
-
- String name;
- HashMap<String,String> args;
- };
-
- _FORCE_INLINE_ Error _parse_array_element(Vector<char> &buff,bool p_number_only,FileAccess *f,bool *end);
-
- mutable int lines;
- uint8_t get_char() const;
- int get_current_line() const;
-
-friend class ObjectFormatLoaderInstancerXML;
- List<Tag> tag_stack;
-
- List<RES> resource_cache;
- Tag* parse_tag(bool* r_exit=NULL);
- Error close_tag(const String& p_name);
- void unquote(String& p_str);
- Error goto_end_of_tag();
- Error parse_property_data(String &r_data);
- Error parse_property(Variant& r_v, String &r_name);
-
-public:
-
-
- virtual Error load(Object **p_object,Variant &p_meta);
-
- virtual ~ObjectFormatLoaderXML();
-};
-
-class ObjectFormatLoaderInstancerXML : public ObjectFormatLoaderInstancer {
-public:
-
- virtual ObjectFormatLoaderXML* instance(const String& p_file,const String& p_magic);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
-
-
-};
-
-#endif
-#endif
-#endif
-#endif
diff --git a/core/io/object_loader.cpp b/core/io/object_loader.cpp
deleted file mode 100644
index bb42cf7338..0000000000
--- a/core/io/object_loader.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************************************/
-/* object_loader.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 "object_loader.h"
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-bool ObjectFormatLoaderInstancer::recognize(const String& p_extension) const {
-
-
- List<String> extensions;
- get_recognized_extensions(&extensions);
- for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- if (E->get().nocasecmp_to(p_extension)==0)
- return true;
- }
-
- return false;
-}
-
-ObjectFormatLoaderInstancer *ObjectLoader::loader[MAX_LOADERS];
-int ObjectLoader::loader_count=0;
-
-
-ObjectFormatLoader *ObjectLoader::instance_format_loader(const String& p_path,const String& p_magic,String p_force_extension) {
-
- String extension=p_force_extension.length()?p_force_extension:p_path.extension();
-
- for (int i=0;i<loader_count;i++) {
-
- if (!loader[i]->recognize(extension))
- continue;
- ObjectFormatLoader *format_loader = loader[i]->instance(p_path,p_magic);
- if (format_loader)
- return format_loader;
- }
-
- return NULL;
-}
-
-void ObjectLoader::get_recognized_extensions(List<String> *p_extensions) {
-
- for (int i=0;i<loader_count;i++) {
-
- loader[i]->get_recognized_extensions(p_extensions);
- }
-}
-
-
-
-void ObjectLoader::add_object_format_loader_instancer(ObjectFormatLoaderInstancer *p_format_loader_instancer) {
-
- ERR_FAIL_COND(loader_count>=MAX_LOADERS );
- loader[loader_count++]=p_format_loader_instancer;
-}
-
-
-#endif
diff --git a/core/io/object_loader.h b/core/io/object_loader.h
deleted file mode 100644
index 9199313f04..0000000000
--- a/core/io/object_loader.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*************************************************************************/
-/* object_loader.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 OBJECT_LOADER_H
-#define OBJECT_LOADER_H
-
-#include "object.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-#ifdef OLD_SCENE_FORMAT_ENABLED
-class ObjectFormatLoader {
-public:
-
- virtual Error load(Object **p_object,Variant &p_meta)=0;
-
- virtual ~ObjectFormatLoader() {}
-};
-
-class ObjectFormatLoaderInstancer {
-public:
-
- virtual ObjectFormatLoader* instance(const String& p_file,const String& p_magic)=0;
- virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
- bool recognize(const String& p_extension) const;
-
- virtual ~ObjectFormatLoaderInstancer() {}
-};
-
-class ObjectLoader {
-
- enum {
- MAX_LOADERS=64
- };
-
- static ObjectFormatLoaderInstancer *loader[MAX_LOADERS];
- static int loader_count;
-
-public:
-
- static ObjectFormatLoader *instance_format_loader(const String& p_path,const String& p_magic,String p_force_extension="");
- static void add_object_format_loader_instancer(ObjectFormatLoaderInstancer *p_format_loader_instancer);
- static void get_recognized_extensions(List<String> *p_extensions);
-
-
-
-};
-
-#endif
-#endif
diff --git a/core/io/object_saver.cpp b/core/io/object_saver.cpp
deleted file mode 100644
index cff2e836a7..0000000000
--- a/core/io/object_saver.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*************************************************************************/
-/* object_saver.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 "object_saver.h"
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-void OptimizedSaver::add_property(const StringName& p_name, const Variant& p_value) {
-
- ERR_FAIL_COND(!_list);
- Property p;
- p.name=p_name;
- p.value=p_value;
- _list->push_back(p);
-}
-
-bool OptimizedSaver::optimize_object(const Object *p_object) {
-
- return false; //not optimize
-}
-
-void OptimizedSaver::get_property_list(const Object* p_object,List<Property> *p_properties) {
-
-
- _list=p_properties;
-
- bool res = call("optimize_object",p_object);
-
- if (!res) {
-
- List<PropertyInfo> plist;
- p_object->get_property_list(&plist);
- for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
-
- PropertyInfo pinfo=E->get();
- if ((pinfo.usage&PROPERTY_USAGE_STORAGE) || (is_bundle_resources_enabled() && pinfo.usage&PROPERTY_USAGE_BUNDLE)) {
-
- add_property(pinfo.name,p_object->get(pinfo.name));
- }
- }
-
- }
-
- _list=NULL;
-}
-
-void OptimizedSaver::set_target_platform(const String& p_platform) {
-
- ERR_FAIL_COND(p_platform!="" && !p_platform.is_valid_identifier());
- platform=p_platform;
-}
-
-String OptimizedSaver::get_target_platform() const {
-
- return platform;
-}
-
-void OptimizedSaver::set_target_name(const String& p_name) {
-
- name=p_name;
-}
-
-String OptimizedSaver::get_target_name() const {
-
- return name;
-}
-
-void OptimizedSaver::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("set_target_platform","name"),&OptimizedSaver::set_target_platform);
- ObjectTypeDB::bind_method(_MD("get_target_platform"),&OptimizedSaver::get_target_platform);
- ObjectTypeDB::bind_method(_MD("set_target_name","name"),&OptimizedSaver::set_target_name);
- ObjectTypeDB::bind_method(_MD("add_property","name","value"),&OptimizedSaver::add_property);
- ObjectTypeDB::bind_method(_MD("optimize_object","obj"),&OptimizedSaver::optimize_object);
-}
-
-OptimizedSaver::OptimizedSaver() {
-
- _list=NULL;
-}
-
-ObjectFormatSaverInstancer *ObjectSaver::saver[MAX_LOADERS];
-int ObjectSaver::saver_count=0;
-
-bool ObjectFormatSaverInstancer::recognize(const String& p_extension) const {
-
-
- List<String> extensions;
- get_recognized_extensions(&extensions);
- for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- if (E->get().nocasecmp_to(p_extension.extension())==0)
- return true;
- }
-
- return false;
-}
-
-ObjectFormatSaver *ObjectSaver::instance_format_saver(const String& p_path,const String& p_magic,String p_force_extension,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer) {
-
- String extension=p_force_extension.length()?p_force_extension:p_path.extension();
-
- for (int i=0;i<saver_count;i++) {
-
- if (!saver[i]->recognize(extension))
- continue;
- ObjectFormatSaver *format_saver = saver[i]->instance(p_path,p_magic,p_flags,p_optimizer);
- if (format_saver)
- return format_saver;
- }
-
- return NULL;
-}
-
-void ObjectSaver::get_recognized_extensions(List<String> *p_extensions) {
-
- for (int i=0;i<saver_count;i++) {
-
- saver[i]->get_recognized_extensions(p_extensions);
- }
-}
-
-
-
-void ObjectSaver::add_object_format_saver_instancer(ObjectFormatSaverInstancer *p_format_saver_instancer) {
-
- ERR_FAIL_COND(saver_count>=MAX_LOADERS );
- saver[saver_count++]=p_format_saver_instancer;
-}
-
-
-
-#endif
diff --git a/core/io/object_saver.h b/core/io/object_saver.h
deleted file mode 100644
index b22f7e05bb..0000000000
--- a/core/io/object_saver.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*************************************************************************/
-/* object_saver.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 OBJECT_SAVER_H
-#define OBJECT_SAVER_H
-
-#include "object.h"
-#include "resource.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-class OptimizedSaver : public Reference {
-
- OBJ_TYPE(OptimizedSaver,Reference);
-public:
-
- struct Property {
-
- StringName name;
- Variant value;
- };
-
-private:
-
- String name;
- String platform;
- List<Property> *_list;
-protected:
-
-
- void set_target_platform(const String& p_platform);
- void set_target_name(const String& p_name);
- void add_property(const StringName& p_name, const Variant& p_value);
- static void _bind_methods();
-
- virtual bool optimize_object(const Object *p_object);
-
-public:
-
-
- virtual bool is_bundle_resources_enabled() const { return false; }
-
- String get_target_platform() const;
- String get_target_name() const;
- void get_property_list(const Object* p_object, List<Property> *p_properties);
-
-
- OptimizedSaver();
-
-};
-
-
-class ObjectFormatSaver {
-public:
-
- virtual Error save(const Object *p_object,const Variant &p_meta=Variant())=0;
-
- virtual ~ObjectFormatSaver() {}
-};
-
-class ObjectFormatSaverInstancer {
-public:
-
- virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
- virtual ObjectFormatSaver* instance(const String& p_file,const String& p_magic="",uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>())=0;
- bool recognize(const String& p_extension) const;
-
- virtual ~ObjectFormatSaverInstancer() {}
-};
-
-class ObjectSaver {
-
- enum {
- MAX_LOADERS=64
- };
-
- static ObjectFormatSaverInstancer *saver[MAX_LOADERS];
- static int saver_count;
-
-public:
-
- enum SaverFlags {
-
- FLAG_RELATIVE_PATHS=1,
- FLAG_BUNDLE_RESOURCES=2,
- FLAG_OMIT_EDITOR_PROPERTIES=4,
- FLAG_SAVE_BIG_ENDIAN=8
- };
-
-
- static ObjectFormatSaver *instance_format_saver(const String& p_path,const String& p_magic,String p_force_extension="",uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>());
- static void get_recognized_extensions(List<String> *p_extensions);
-
- static void add_object_format_saver_instancer(ObjectFormatSaverInstancer *p_format_saver_instancer);
-
-
-};
-
-#endif
-#endif
diff --git a/core/io/object_saver_base.cpp b/core/io/object_saver_base.cpp
deleted file mode 100644
index 94d715de28..0000000000
--- a/core/io/object_saver_base.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*************************************************************************/
-/* object_saver_base.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 "object_saver_base.h"
-#ifdef OLD_SCENE_FORMAT_ENABLED
-void ObjectSaverBase::_find_resources(const Variant& p_variant) {
-
- switch(p_variant.get_type()) {
- case Variant::OBJECT: {
-
-
- RES res = p_variant.operator RefPtr();
-
- if (res.is_null() || (res->get_path().length() && res->get_path().find("::") == -1 ))
- return;
-
- if (resource_map.has(res))
- return;
-
- List<PropertyInfo> property_list;
-
- res->get_property_list( &property_list );
-
- List<PropertyInfo>::Element *I=property_list.front();
-
- while(I) {
-
- PropertyInfo pi=I->get();
-
- if (pi.usage&PROPERTY_USAGE_STORAGE) {
-
- if (pi.type==Variant::OBJECT) {
-
- Variant v=res->get(I->get().name);
- _find_resources(v);
- }
- }
-
- I=I->next();
- }
-
- resource_map[ res ] = resource_map.size(); //saved after, so the childs it needs are available when loaded
- saved_resources.push_back(res);
-
- } break;
-
- case Variant::ARRAY: {
-
- Array varray=p_variant;
- int len=varray.size();
- for(int i=0;i<len;i++) {
-
- Variant v=varray.get(i);
- _find_resources(v);
- }
-
- } break;
-
- case Variant::DICTIONARY: {
-
- Dictionary d=p_variant;
- List<Variant> keys;
- d.get_key_list(&keys);
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- Variant v = d[E->get()];
- _find_resources(v);
- }
- } break;
- default: {}
- }
-
-}
-
-
-Error ObjectSaverBase::save(const Object *p_object,const Variant &p_meta) {
-
- ERR_EXPLAIN("write_object should supply either an object, a meta, or both");
- ERR_FAIL_COND_V(!p_object && p_meta.get_type()==Variant::NIL, ERR_INVALID_PARAMETER);
-
- SavedObject *so = memnew( SavedObject );
-
- if (p_object) {
- so->type=p_object->get_type();
- };
-
- _find_resources(p_meta);
- so->meta=p_meta;
-
- if (p_object) {
-
- List<PropertyInfo> property_list;
- p_object->get_property_list( &property_list );
-
- List<PropertyInfo>::Element *I=property_list.front();
-
- while(I) {
-
- if (I->get().usage&PROPERTY_USAGE_STORAGE) {
-
- SavedObject::SavedProperty sp;
- sp.name=I->get().name;
- sp.value = p_object->get(I->get().name);
- _find_resources(sp.value);
- so->properties.push_back(sp);
- }
-
- I=I->next();
- }
-
- }
-
- saved_objects.push_back(so);
-
- return OK;
-}
-
-ObjectSaverBase::ObjectSaverBase() {
-
-};
-
-ObjectSaverBase::~ObjectSaverBase() {
-
-};
-#endif
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_xml.cpp b/core/io/resource_format_xml.cpp
index e6eede7de6..75384d4ab6 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);
}
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/math/geometry.cpp b/core/math/geometry.cpp
index cb76b9ed0f..2d525dd1ce 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -1004,3 +1004,134 @@ DVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height, in
}
+
+struct _AtlasWorkRect {
+
+ Size2i s;
+ Point2i p;
+ int idx;
+ _FORCE_INLINE_ bool operator<(const _AtlasWorkRect& p_r) const { return s.width > p_r.s.width; };
+};
+
+struct _AtlasWorkRectResult {
+
+ Vector<_AtlasWorkRect> result;
+ int max_w;
+ int max_h;
+};
+
+void Geometry::make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size) {
+
+ //super simple, almost brute force scanline stacking fitter
+ //it's pretty basic for now, but it tries to make sure that the aspect ratio of the
+ //resulting atlas is somehow square. This is necesary because video cards have limits
+ //on texture size (usually 2048 or 4096), so the more square a texture, the more chances
+ //it will work in every hardware.
+ // for example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
+ // 256x8192 atlas (won't work anywhere).
+
+ ERR_FAIL_COND(p_rects.size()==0);
+
+ Vector<_AtlasWorkRect> wrects;
+ wrects.resize(p_rects.size());
+ for(int i=0;i<p_rects.size();i++) {
+ wrects[i].s=p_rects[i];
+ wrects[i].idx=i;
+ }
+ wrects.sort();
+ int widest = wrects[0].s.width;
+
+ Vector<_AtlasWorkRectResult> results;
+
+ for(int i=0;i<=12;i++) {
+
+ int w = 1<<i;
+ int max_h=0;
+ int max_w=0;
+ if ( w < widest )
+ continue;
+
+ Vector<int> hmax;
+ hmax.resize(w);
+ for(int j=0;j<w;j++)
+ hmax[j]=0;
+
+ //place them
+ int ofs=0;
+ int limit_h=0;
+ for(int j=0;j<wrects.size();j++) {
+
+
+ if (ofs+wrects[j].s.width > w) {
+
+ ofs=0;
+ }
+
+ int from_y=0;
+ for(int k=0;k<wrects[j].s.width;k++) {
+
+ if (hmax[ofs+k] > from_y)
+ from_y=hmax[ofs+k];
+ }
+
+ wrects[j].p.x=ofs;
+ wrects[j].p.y=from_y;
+ int end_h = from_y+wrects[j].s.height;
+ int end_w = ofs+wrects[j].s.width;
+ if (ofs==0)
+ limit_h=end_h;
+
+ for(int k=0;k<wrects[j].s.width;k++) {
+
+ hmax[ofs+k]=end_h;
+ }
+
+ if (end_h > max_h)
+ max_h=end_h;
+
+ if (end_w > max_w)
+ max_w=end_w;
+
+ if (ofs==0 || end_h>limit_h ) //while h limit not reched, keep stacking
+ ofs+=wrects[j].s.width;
+
+ }
+
+ _AtlasWorkRectResult result;
+ result.result=wrects;
+ result.max_h=max_h;
+ result.max_w=max_w;
+ results.push_back(result);
+
+ }
+
+ //find the result with the best aspect ratio
+
+ int best=-1;
+ float best_aspect=1e20;
+
+ for(int i=0;i<results.size();i++) {
+
+ float h = nearest_power_of_2(results[i].max_h);
+ float w = nearest_power_of_2(results[i].max_w);
+ float aspect = h>w ? h/w : w/h;
+ if (aspect < best_aspect) {
+ best=i;
+ best_aspect=aspect;
+ }
+ }
+
+ r_result.resize(p_rects.size());
+
+ for(int i=0;i<p_rects.size();i++) {
+
+ r_result[ results[best].result[i].idx ]=results[best].result[i].p;
+ }
+
+ r_size=Size2(results[best].max_w,results[best].max_h );
+
+}
+
+
+
+
diff --git a/core/math/geometry.h b/core/math/geometry.h
index 5b21c25bec..81530e30c0 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -821,12 +821,67 @@ public:
};
+
+ _FORCE_INLINE_ static int get_uv84_normal_bit(const Vector3& p_vector) {
+
+ int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*4.0/Math_PI+0.5));
+
+ if (lat==0) {
+ return 24;
+ } else if (lat==4) {
+ return 25;
+ }
+
+ int lon = Math::fast_ftoi(Math::floor( (Math_PI+Math::atan2(p_vector.x,p_vector.z))*8.0/(Math_PI*2.0) + 0.5))%8;
+
+ return lon+(lat-1)*8;
+ }
+
+ _FORCE_INLINE_ static int get_uv84_normal_bit_neighbors(int p_idx) {
+
+ if (p_idx==24) {
+ return 1|2|4|8;
+ } else if (p_idx==25) {
+ return (1<<23)|(1<<22)|(1<<21)|(1<<20);
+ } else {
+
+ int ret = 0;
+ if ((p_idx%8) == 0)
+ ret|=(1<<(p_idx+7));
+ else
+ ret|=(1<<(p_idx-1));
+ if ((p_idx%8) == 7)
+ ret|=(1<<(p_idx-7));
+ else
+ ret|=(1<<(p_idx+1));
+
+ int mask = ret|(1<<p_idx);
+ if (p_idx<8)
+ ret|=24;
+ else
+ ret|=mask>>8;
+
+ if (p_idx>=16)
+ ret|=25;
+ else
+ ret|=mask<<8;
+
+ return ret;
+ }
+
+ }
+
+
+
+
static MeshData build_convex_mesh(const DVector<Plane> &p_planes);
static DVector<Plane> build_sphere_planes(float p_radius, int p_lats, int p_lons, Vector3::Axis p_axis=Vector3::AXIS_Z);
static DVector<Plane> build_box_planes(const Vector3& p_extents);
static DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
static DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
-
+
+ static void make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size);
+
};
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 ed30de6915..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);
@@ -428,6 +428,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me
List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left;
ERR_CONTINUE(O==E);
+ ERR_CONTINUE(O==NULL);
if (O->get().plane.is_almost_like(f.plane)) {
//merge and delete edge and contiguous face, while repointing edges (uuugh!)
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..82144ab4be 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1489,7 +1489,7 @@ 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);
@@ -1694,6 +1694,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..97ca50cb1a 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,
@@ -582,6 +583,7 @@ 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)
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/input.cpp b/core/os/input.cpp
index 4151c1b5a8..a827e75896 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() {
@@ -69,6 +70,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..d4deff2f5e 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>
*/
@@ -286,6 +287,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 +338,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 +349,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 473cf8706f..4935136eeb 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -27,10 +27,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_core_types.h"
-#include "io/object_format_xml.h"
-#include "io/object_format_binary.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"
@@ -56,14 +55,6 @@
#ifdef XML_ENABLED
static ResourceFormatSaverXML *resource_saver_xml=NULL;
static ResourceFormatLoaderXML *resource_loader_xml=NULL;
-#ifdef OLD_SCENE_FORMAT_ENABLED
-static ObjectFormatSaverInstancerXML *object_format_saver_xml=NULL;
-static ObjectFormatLoaderInstancerXML *object_format_loader_xml=NULL;
-#endif
-#endif
-#ifdef OLD_SCENE_FORMAT_ENABLED
-static ObjectFormatSaverInstancerBinary * object_format_saver_binary = NULL;
-static ObjectFormatLoaderInstancerBinary * object_format_loader_binary = NULL;
#endif
static ResourceFormatSaverBinary *resource_saver_binary=NULL;
static ResourceFormatLoaderBinary *resource_loader_binary=NULL;
@@ -101,23 +92,6 @@ void register_core_types() {
CoreStringNames::create();
-#ifdef XML_ENABLED
-#ifdef OLD_SCENE_FORMAT_ENABLED
- object_format_saver_xml = memnew( ObjectFormatSaverInstancerXML );
- ObjectSaver::add_object_format_saver_instancer( object_format_saver_xml );
-
- object_format_loader_xml = memnew( ObjectFormatLoaderInstancerXML );
- ObjectLoader::add_object_format_loader_instancer( object_format_loader_xml );
-#endif
-#endif
-#ifdef OLD_SCENE_FORMAT_ENABLED
- object_format_saver_binary = memnew( ObjectFormatSaverInstancerBinary );
- ObjectSaver::add_object_format_saver_instancer( object_format_saver_binary );
-
-
- object_format_loader_binary = memnew( ObjectFormatLoaderInstancerBinary );
- ObjectLoader::add_object_format_loader_instancer( object_format_loader_binary );
-#endif
resource_format_po = memnew( TranslationLoaderPO );
ResourceLoader::add_resource_format_loader( resource_format_po );
@@ -136,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>();
@@ -212,10 +188,6 @@ void unregister_core_types() {
memdelete( _geometry );
#ifdef XML_ENABLED
-#ifdef OLD_SCENE_FORMAT_ENABLED
- memdelete( object_format_saver_xml );
- memdelete( object_format_loader_xml );
-#endif
if (resource_saver_xml)
memdelete(resource_saver_xml);
if (resource_loader_xml)
@@ -228,10 +200,6 @@ void unregister_core_types() {
memdelete(resource_loader_binary);
-#ifdef OLD_SCENE_FORMAT_ENABLED
- memdelete( object_format_saver_binary );
- memdelete( object_format_loader_binary );
-#endif
memdelete( resource_format_po );
if (ip)
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/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 cd33c276a8..581cc29440 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -555,6 +555,42 @@ String String::get_slice(String p_splitter, int p_slice) const {
}
+
+Vector<String> String::split_spaces() const {
+
+ Vector<String> ret;
+ int from=0;
+ int i=0;
+ int len = length();
+ bool inside=false;
+
+ while(true) {
+
+ bool empty=operator[](i)<33;
+
+ if (i==0)
+ inside=!empty;
+
+ if (!empty && !inside) {
+ inside=true;
+ from=i;
+ }
+
+ if (empty && inside) {
+
+ ret.push_back(substr(from,i-from));
+ inside=false;
+ }
+
+ if (i==len)
+ break;
+ i++;
+ }
+
+ return ret;
+
+}
+
Vector<String> String::split(const String &p_splitter,bool p_allow_empty) const {
Vector<String> ret;
@@ -590,7 +626,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;
@@ -618,8 +654,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;
@@ -1923,8 +1960,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);
@@ -2017,6 +2056,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) {
@@ -3401,7 +3441,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};
diff --git a/core/ustring.h b/core/ustring.h
index 4831341866..e1d6761742 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -142,7 +142,7 @@ 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;
@@ -150,6 +150,7 @@ public:
String get_slice(String p_splitter,int p_slice) const;
Vector<String> split(const String &p_splitter,bool p_allow_empty=true) const;
+ Vector<String> split_spaces() const;
Vector<float> split_floats(const String &p_splitter,bool p_allow_empty=true) const;
Vector<float> split_floats_mk(const Vector<String> &p_splitters,bool p_allow_empty=true) const;
Vector<int> split_ints(const String &p_splitter,bool p_allow_empty=true) const;
diff --git a/core/variant.cpp b/core/variant.cpp
index fdb14c0c0f..2f0eca9e91 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -2631,3 +2631,129 @@ Variant Variant::call(const StringName& p_method,VARIANT_ARG_DECLARE) {
return ret;
}
+
+String Variant::get_construct_string() 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)+"\"";
+ 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 "@\""+operator NodePath()+"\"";
+ 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();
+ sp.value=d[E->get()].get_construct_string();
+ 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="[";
+ 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="[";
+ 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="[";
+ 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="[";
+ 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();
+ };
+ return str+"]";
+
+ } break;
+ case OBJECT: {
+
+ if (_get_obj().obj)
+ 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..47fc3f43ac 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,8 @@ public:
static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value);
static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value);
+ String get_construct_string() const;
+
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 e0ae7e2114..3f2800494d 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -515,7 +515,7 @@ static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Varian
#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)\
-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]); }
+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]); }
#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)\
@@ -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);
@@ -551,6 +552,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_PTR3R(Image, resized);
VCALL_PTR0R(Image, get_data);
VCALL_PTR3(Image, blit_rect);
+ VCALL_PTR1R(Image, converted);
VCALL_PTR0R( AABB, get_area );
VCALL_PTR0R( AABB, has_no_area );
@@ -605,6 +607,25 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
}
}
+ static void _call_Matrix32_basis_xform(Variant& r_ret,Variant& p_self,const Variant** p_args) {
+
+ switch(p_args[0]->type) {
+
+ case Variant::VECTOR2: r_ret=reinterpret_cast<Matrix32*>(p_self._data._ptr)->basis_xform( p_args[0]->operator Vector2()); return;
+ default: r_ret=Variant();
+ }
+
+ }
+
+ static void _call_Matrix32_basis_xform_inv(Variant& r_ret,Variant& p_self,const Variant** p_args) {
+
+ switch(p_args[0]->type) {
+
+ case Variant::VECTOR2: r_ret=reinterpret_cast<Matrix32*>(p_self._data._ptr)->basis_xform_inv( p_args[0]->operator Vector2()); return;
+ default: r_ret=Variant();
+ }
+ }
+
VCALL_PTR0R( Matrix3, inverse );
VCALL_PTR0R( Matrix3, transposed );
@@ -664,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 {
@@ -735,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]);
@@ -1305,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));
@@ -1313,6 +1341,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC3(IMAGE, IMAGE, Image, resized, INT, "x", INT, "y", INT, "interpolation", varray(((int)Image::INTERPOLATE_BILINEAR)));
ADDFUNC0(IMAGE, RAW_ARRAY, Image, get_data, varray());
ADDFUNC3(IMAGE, NIL, Image, blit_rect, IMAGE, "src", RECT2, "src_rect", VECTOR2, "dest", varray(0));
+ ADDFUNC1(IMAGE, IMAGE, Image, converted, INT, "format", varray(0));
ADDFUNC0(_RID,INT,RID,get_id,varray());
@@ -1430,6 +1459,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,translated,VECTOR2,"offset",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform,NIL,"v",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform_inv,NIL,"v",varray());
+ ADDFUNC1(MATRIX32,MATRIX32,Matrix32,basis_xform,NIL,"v",varray());
+ ADDFUNC1(MATRIX32,MATRIX32,Matrix32,basis_xform_inv,NIL,"v",varray());
ADDFUNC2(MATRIX32,MATRIX32,Matrix32,interpolate_with,MATRIX32,"m",REAL,"c",varray());
ADDFUNC0(MATRIX3,MATRIX3,Matrix3,inverse,varray());
@@ -1465,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 */
@@ -1482,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_op.cpp b/core/variant_op.cpp
index 9c489c5ef2..ec43b1275c 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -922,21 +922,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 +961,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 +1055,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) {
diff --git a/demos/2d/hexamap/.fscache b/demos/2d/hexamap/.fscache
new file mode 100644
index 0000000000..60aa69b645
--- /dev/null
+++ b/demos/2d/hexamap/.fscache
@@ -0,0 +1,33 @@
+::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/hexamap/WWT-01.png b/demos/2d/hexamap/WWT-01.png
new file mode 100644
index 0000000000..79d75fa4c9
--- /dev/null
+++ b/demos/2d/hexamap/WWT-01.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-02.png b/demos/2d/hexamap/WWT-02.png
new file mode 100644
index 0000000000..7dcd1c8cca
--- /dev/null
+++ b/demos/2d/hexamap/WWT-02.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-03.png b/demos/2d/hexamap/WWT-03.png
new file mode 100644
index 0000000000..1e76c9a24d
--- /dev/null
+++ b/demos/2d/hexamap/WWT-03.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-04.png b/demos/2d/hexamap/WWT-04.png
new file mode 100644
index 0000000000..84a3b90e71
--- /dev/null
+++ b/demos/2d/hexamap/WWT-04.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-05.png b/demos/2d/hexamap/WWT-05.png
new file mode 100644
index 0000000000..850747dc8d
--- /dev/null
+++ b/demos/2d/hexamap/WWT-05.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-06.png b/demos/2d/hexamap/WWT-06.png
new file mode 100644
index 0000000000..52479e2d26
--- /dev/null
+++ b/demos/2d/hexamap/WWT-06.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-07.png b/demos/2d/hexamap/WWT-07.png
new file mode 100644
index 0000000000..87aa8a4102
--- /dev/null
+++ b/demos/2d/hexamap/WWT-07.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-08.png b/demos/2d/hexamap/WWT-08.png
new file mode 100644
index 0000000000..0234cccd56
--- /dev/null
+++ b/demos/2d/hexamap/WWT-08.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-09.png b/demos/2d/hexamap/WWT-09.png
new file mode 100644
index 0000000000..5467eb58c3
--- /dev/null
+++ b/demos/2d/hexamap/WWT-09.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-10.png b/demos/2d/hexamap/WWT-10.png
new file mode 100644
index 0000000000..bb0b5ae1ff
--- /dev/null
+++ b/demos/2d/hexamap/WWT-10.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-11.png b/demos/2d/hexamap/WWT-11.png
new file mode 100644
index 0000000000..926ad251b4
--- /dev/null
+++ b/demos/2d/hexamap/WWT-11.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-12.png b/demos/2d/hexamap/WWT-12.png
new file mode 100644
index 0000000000..e6c7d33894
--- /dev/null
+++ b/demos/2d/hexamap/WWT-12.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-13.png b/demos/2d/hexamap/WWT-13.png
new file mode 100644
index 0000000000..f14e42af6e
--- /dev/null
+++ b/demos/2d/hexamap/WWT-13.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-14.png b/demos/2d/hexamap/WWT-14.png
new file mode 100644
index 0000000000..826ed49d18
--- /dev/null
+++ b/demos/2d/hexamap/WWT-14.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-15.png b/demos/2d/hexamap/WWT-15.png
new file mode 100644
index 0000000000..c62de67c8e
--- /dev/null
+++ b/demos/2d/hexamap/WWT-15.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-16.png b/demos/2d/hexamap/WWT-16.png
new file mode 100644
index 0000000000..2e8c289d97
--- /dev/null
+++ b/demos/2d/hexamap/WWT-16.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-17.png b/demos/2d/hexamap/WWT-17.png
new file mode 100644
index 0000000000..f8c59a4dbe
--- /dev/null
+++ b/demos/2d/hexamap/WWT-17.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-18.png b/demos/2d/hexamap/WWT-18.png
new file mode 100644
index 0000000000..05269c843c
--- /dev/null
+++ b/demos/2d/hexamap/WWT-18.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-19.png b/demos/2d/hexamap/WWT-19.png
new file mode 100644
index 0000000000..7313ff8871
--- /dev/null
+++ b/demos/2d/hexamap/WWT-19.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-20.png b/demos/2d/hexamap/WWT-20.png
new file mode 100644
index 0000000000..2ec6fe94e2
--- /dev/null
+++ b/demos/2d/hexamap/WWT-20.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-21.png b/demos/2d/hexamap/WWT-21.png
new file mode 100644
index 0000000000..e7a51fa687
--- /dev/null
+++ b/demos/2d/hexamap/WWT-21.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-22.png b/demos/2d/hexamap/WWT-22.png
new file mode 100644
index 0000000000..0e4d7729ed
--- /dev/null
+++ b/demos/2d/hexamap/WWT-22.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-23.png b/demos/2d/hexamap/WWT-23.png
new file mode 100644
index 0000000000..ab1cc895e4
--- /dev/null
+++ b/demos/2d/hexamap/WWT-23.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-24.png b/demos/2d/hexamap/WWT-24.png
new file mode 100644
index 0000000000..b0a05671cf
--- /dev/null
+++ b/demos/2d/hexamap/WWT-24.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-25.png b/demos/2d/hexamap/WWT-25.png
new file mode 100644
index 0000000000..3d90080259
--- /dev/null
+++ b/demos/2d/hexamap/WWT-25.png
Binary files differ
diff --git a/demos/2d/hexamap/WWT-26.png b/demos/2d/hexamap/WWT-26.png
new file mode 100644
index 0000000000..a3baca90a0
--- /dev/null
+++ b/demos/2d/hexamap/WWT-26.png
Binary files differ
diff --git a/demos/2d/hexamap/engine.cfg b/demos/2d/hexamap/engine.cfg
new file mode 100644
index 0000000000..4567af7a16
--- /dev/null
+++ b/demos/2d/hexamap/engine.cfg
@@ -0,0 +1,12 @@
+[application]
+
+name="Hexagonal Game"
+main_scene="res://map.scn"
+icon="res://icon.png"
+
+[input]
+
+move_up=[key(Up)]
+move_left=[key(Left)]
+move_right=[key(Right)]
+move_bottom=[key(Down)]
diff --git a/demos/2d/hexamap/icon.png b/demos/2d/hexamap/icon.png
new file mode 100644
index 0000000000..0fcef95111
--- /dev/null
+++ b/demos/2d/hexamap/icon.png
Binary files differ
diff --git a/demos/2d/hexamap/map.scn b/demos/2d/hexamap/map.scn
new file mode 100644
index 0000000000..5798aab850
--- /dev/null
+++ b/demos/2d/hexamap/map.scn
Binary files differ
diff --git a/demos/2d/hexamap/tiles.scn b/demos/2d/hexamap/tiles.scn
new file mode 100644
index 0000000000..265aedac2b
--- /dev/null
+++ b/demos/2d/hexamap/tiles.scn
Binary files differ
diff --git a/demos/2d/hexamap/tileset.res b/demos/2d/hexamap/tileset.res
new file mode 100644
index 0000000000..05d89316a2
--- /dev/null
+++ b/demos/2d/hexamap/tileset.res
Binary files differ
diff --git a/demos/2d/hexamap/troll.gd b/demos/2d/hexamap/troll.gd
new file mode 100644
index 0000000000..d118d3a2ba
--- /dev/null
+++ b/demos/2d/hexamap/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/hexamap/troll.png b/demos/2d/hexamap/troll.png
new file mode 100644
index 0000000000..69f195d034
--- /dev/null
+++ b/demos/2d/hexamap/troll.png
Binary files differ
diff --git a/demos/2d/hexamap/troll.scn b/demos/2d/hexamap/troll.scn
new file mode 100644
index 0000000000..f5d87c3631
--- /dev/null
+++ b/demos/2d/hexamap/troll.scn
Binary files differ
diff --git a/demos/2d/isometric/bastiles.res b/demos/2d/isometric/bastiles.res
new file mode 100644
index 0000000000..2161c88f1e
--- /dev/null
+++ b/demos/2d/isometric/bastiles.res
Binary files differ
diff --git a/demos/2d/isometric/dungeon.scn b/demos/2d/isometric/dungeon.scn
new file mode 100644
index 0000000000..76532a44aa
--- /dev/null
+++ b/demos/2d/isometric/dungeon.scn
Binary files differ
diff --git a/demos/2d/isometric/engine.cfg b/demos/2d/isometric/engine.cfg
new file mode 100644
index 0000000000..48f39826f9
--- /dev/null
+++ b/demos/2d/isometric/engine.cfg
@@ -0,0 +1,21 @@
+[application]
+
+name="Isometric Game"
+main_scene="res://dungeon.scn"
+icon="res://icon.png"
+
+[image_loader]
+
+filter=false
+gen_mipmaps=false
+
+[input]
+
+move_up=[key(Up)]
+move_left=[key(Left)]
+move_right=[key(Right)]
+move_bottom=[key(Down)]
+
+[rasterizer]
+
+use_pixel_snap=true
diff --git a/demos/2d/isometric/icon.png b/demos/2d/isometric/icon.png
new file mode 100644
index 0000000000..c8fb5dcb42
--- /dev/null
+++ b/demos/2d/isometric/icon.png
Binary files differ
diff --git a/demos/2d/isometric/isotiles.png b/demos/2d/isometric/isotiles.png
new file mode 100644
index 0000000000..aa5a800f8f
--- /dev/null
+++ b/demos/2d/isometric/isotiles.png
Binary files differ
diff --git a/demos/2d/isometric/tileset.scn b/demos/2d/isometric/tileset.scn
new file mode 100644
index 0000000000..edb0bc0276
--- /dev/null
+++ b/demos/2d/isometric/tileset.scn
Binary files differ
diff --git a/demos/2d/isometric/troll.gd b/demos/2d/isometric/troll.gd
new file mode 100644
index 0000000000..d118d3a2ba
--- /dev/null
+++ b/demos/2d/isometric/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/isometric/troll.png b/demos/2d/isometric/troll.png
new file mode 100644
index 0000000000..69f195d034
--- /dev/null
+++ b/demos/2d/isometric/troll.png
Binary files differ
diff --git a/demos/2d/isometric/troll.scn b/demos/2d/isometric/troll.scn
new file mode 100644
index 0000000000..f5d87c3631
--- /dev/null
+++ b/demos/2d/isometric/troll.scn
Binary files differ
diff --git a/demos/2d/kinematic_char/colworld.scn b/demos/2d/kinematic_char/colworld.scn
index b3a0a1f168..7b79a1d887 100644
--- a/demos/2d/kinematic_char/colworld.scn
+++ b/demos/2d/kinematic_char/colworld.scn
Binary files differ
diff --git a/demos/2d/kinematic_char/player.gd b/demos/2d/kinematic_char/player.gd
index 5c56477758..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
@@ -74,6 +75,9 @@ func _fixed_process(delta):
var floor_velocity=Vector2()
if (is_colliding()):
+ # you can check which tile was collision against with this
+ # print(get_collider_metadata())
+
#ran against something, is it the floor? get normal
var n = get_collision_normal()
diff --git a/demos/2d/kinematic_char/player.scn b/demos/2d/kinematic_char/player.scn
index 126b332184..5809c0e98a 100644
--- a/demos/2d/kinematic_char/player.scn
+++ b/demos/2d/kinematic_char/player.scn
Binary files differ
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..e2943d8fcf 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">
+<resource_file type="PackedScene" subresource_count="9" version="1.0" version_name="Godot Engine v1.0.stable.custom_build">
<ext_resource path="res://tileset.xml" type="TileSet"></ext_resource>
<ext_resource path="res://music.ogg" type="AudioStream"></ext_resource>
- <ext_resource path="res://coin.xml" type="PackedScene"></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://enemy.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://parallax_bg.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>
<main_resource>
<dictionary name="_bundled" shared="false">
<string> "names" </string>
- <string_array len="122">
+ <string_array len="125">
<string> "stage" </string>
<string> "Node" </string>
<string> "_import_path" </string>
@@ -25,13 +25,16 @@
<string> "transform/pos" </string>
<string> "transform/rot" </string>
<string> "transform/scale" </string>
- <string> "cell_size" </string>
- <string> "quadrant_size" </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> "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 +145,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>
@@ -174,6 +177,8 @@
</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 +192,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 +208,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 +224,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 +240,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 +254,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,7 +276,7 @@
<int> 0 </int>
</dictionary>
<string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
+ <string> "Script" </string>
</dictionary>
<bool> True </bool>
<real> 1 </real>
@@ -265,11 +284,14 @@
<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>
+ <vector2> 64, 64 </vector2>
+ <int> 16 </int>
+ <matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
+ <int> 2 </int>
<int> 1 </int>
+ <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>
<dictionary shared="false">
<string> "_edit_lock_" </string>
<bool> True </bool>
@@ -280,6 +302,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 +455,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> "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> "zfar" </string>
+ <real> 500 </real>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
+ <string> "fov" </string>
+ <real> 45 </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 +705,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 +927,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.&#22;This version uses physics and the 2D physics engine for motion and collision.&#22;&#22;The demo also shows the benefits of using the scene system, where coins,&#22;enemies and the player are edited separatedly and instanced in the stage.&#22;&#22;To edit the base tiles for the tileset, open the tileset_edit.xml file and follow &#22;instructions.&#22;" </string>
- <int> 0 </int>
+ <string> "This is a simple demo on how to make a platformer game with Godot.&quot;This version uses physics and the 2D physics engine for motion and collision.&quot;&quot;The demo also shows the benefits of using the scene system, where coins,&quot;enemies and the player are edited separatedly and instanced in the stage.&quot;&quot;To edit the base tiles for the tileset, open the tileset_edit.xml file and follow &quot;instructions.&quot;" </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="950"> -1, -1, 1, 0, -1, 2, 2, 0, 3, 1, 0, 0, 0, 5, 4, -1, 19, 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, 12, 18, 13, 19, 3, 20, 6, 21, 14, 22, 15, 3, 16, 0, 0, 0, 1, 23, -1, 2, 2, 0, 3, 17, 0, 2, 0, 25, 24, 18, 3, 2, 0, 10, 19, 3, 20, 0, 2, 0, 25, 26, 18, 3, 2, 0, 10, 21, 3, 20, 0, 2, 0, 25, 27, 18, 3, 2, 0, 10, 22, 3, 20, 0, 2, 0, 25, 28, 18, 3, 2, 0, 10, 23, 3, 20, 0, 2, 0, 25, 29, 18, 3, 2, 0, 10, 24, 3, 20, 0, 2, 0, 25, 30, 18, 3, 2, 0, 10, 25, 3, 20, 0, 2, 0, 25, 31, 18, 3, 2, 0, 10, 26, 3, 20, 0, 2, 0, 25, 32, 18, 3, 2, 0, 10, 27, 3, 20, 0, 2, 0, 25, 33, 18, 3, 2, 0, 10, 28, 3, 20, 0, 2, 0, 25, 34, 18, 3, 2, 0, 10, 29, 3, 20, 0, 2, 0, 25, 35, 18, 3, 2, 0, 10, 30, 3, 20, 0, 2, 0, 25, 36, 18, 3, 2, 0, 10, 31, 3, 20, 0, 2, 0, 25, 37, 18, 3, 2, 0, 10, 32, 3, 20, 0, 2, 0, 25, 38, 18, 3, 2, 0, 10, 33, 3, 20, 0, 2, 0, 25, 39, 18, 3, 2, 0, 10, 34, 3, 20, 0, 2, 0, 25, 40, 18, 3, 2, 0, 10, 35, 3, 20, 0, 2, 0, 25, 41, 18, 3, 2, 0, 10, 36, 3, 20, 0, 2, 0, 25, 42, 18, 3, 2, 0, 10, 37, 3, 20, 0, 2, 0, 25, 43, 18, 3, 2, 0, 10, 38, 3, 20, 0, 2, 0, 25, 44, 18, 3, 2, 0, 10, 39, 3, 20, 0, 2, 0, 25, 45, 18, 3, 2, 0, 10, 40, 3, 20, 0, 2, 0, 25, 46, 18, 3, 2, 0, 10, 41, 3, 20, 0, 2, 0, 25, 47, 18, 3, 2, 0, 10, 42, 3, 20, 0, 2, 0, 25, 48, 18, 3, 2, 0, 10, 43, 3, 20, 0, 2, 0, 25, 49, 18, 3, 2, 0, 10, 44, 3, 20, 0, 2, 0, 25, 50, 18, 3, 2, 0, 10, 45, 3, 20, 0, 2, 0, 25, 51, 18, 3, 2, 0, 10, 46, 3, 20, 0, 2, 0, 25, 52, 18, 3, 2, 0, 10, 47, 3, 20, 0, 2, 0, 25, 53, 18, 3, 2, 0, 10, 48, 3, 20, 0, 2, 0, 25, 54, 18, 3, 2, 0, 10, 49, 3, 20, 0, 2, 0, 25, 55, 18, 3, 2, 0, 10, 50, 3, 20, 0, 2, 0, 25, 56, 18, 3, 2, 0, 10, 51, 3, 20, 0, 2, 0, 25, 57, 18, 3, 2, 0, 10, 52, 3, 20, 0, 2, 0, 25, 58, 18, 3, 2, 0, 10, 53, 3, 20, 0, 2, 0, 25, 59, 18, 3, 2, 0, 10, 54, 3, 20, 0, 2, 0, 25, 60, 18, 3, 2, 0, 10, 55, 3, 20, 0, 2, 0, 25, 61, 18, 3, 2, 0, 10, 56, 3, 20, 0, 2, 0, 25, 62, 18, 3, 2, 0, 10, 57, 3, 20, 0, 2, 0, 25, 63, 18, 3, 2, 0, 10, 58, 3, 20, 0, 2, 0, 25, 64, 18, 3, 2, 0, 10, 59, 3, 20, 0, 2, 0, 25, 65, 18, 3, 2, 0, 10, 60, 3, 20, 0, 2, 0, 25, 66, 18, 3, 2, 0, 10, 61, 3, 20, 0, 0, 0, 68, 67, 62, 3, 2, 0, 10, 63, 3, 64, 0, 0, 0, 1, 69, -1, 1, 2, 0, 0, 46, 0, 71, 70, 65, 5, 2, 0, 10, 66, 3, 67, 72, 68, 73, 69, 0, 46, 0, 71, 74, 65, 5, 2, 0, 10, 70, 3, 67, 72, 71, 73, 72, 0, 46, 0, 71, 75, 65, 5, 2, 0, 10, 73, 3, 67, 72, 74, 73, 72, 0, 46, 0, 71, 76, 75, 3, 2, 0, 10, 76, 3, 77, 0, 0, 0, 78, 77, -1, 7, 2, 0, 79, 78, 80, 4, 81, 2, 82, 79, 83, 2, 84, 4, 0, 0, 0, 1, 85, -1, 1, 2, 0, 0, 52, 0, 68, 86, 80, 3, 2, 0, 10, 81, 3, 82, 0, 52, 0, 68, 87, 80, 3, 2, 0, 10, 83, 3, 82, 0, 52, 0, 68, 88, 80, 3, 2, 0, 10, 84, 3, 82, 0, 52, 0, 68, 89, 80, 3, 2, 0, 10, 85, 3, 82, 0, 52, 0, 68, 90, 80, 3, 2, 0, 10, 86, 3, 82, 0, 52, 0, 68, 91, 80, 3, 2, 0, 10, 87, 3, 82, 0, 52, 0, 68, 92, 80, 3, 2, 0, 10, 88, 3, 82, 0, 52, 0, 68, 93, 80, 3, 2, 0, 10, 89, 3, 82, 0, 52, 0, 68, 94, 80, 3, 2, 0, 10, 90, 3, 82, 0, 52, 0, 68, 95, 80, 3, 2, 0, 10, 91, 3, 82, 0, 52, 0, 68, 96, 80, 3, 2, 0, 10, 92, 3, 82, 0, 0, 0, 98, 97, 93, 2, 2, 0, 3, 94, 0, 0, 0, 99, 99, -1, 30, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 100, 95, 101, 96, 102, 97, 103, 98, 104, 0, 105, 0, 106, 0, 107, 0, 108, 2, 109, 2, 110, 13, 111, 3, 112, 6, 113, 99, 114, 3, 115, 100, 116, 6, 117, 4, 118, 4, 119, 101, 120, 8, 121, 8, 122, 2, 123, 4, 124, 102, 0 </int_array>
<string> "conns" </string>
<int_array len="0"> </int_array>
</dictionary>
diff --git a/demos/2d/shower_of_bullets/bullet.png b/demos/2d/shower_of_bullets/bullet.png
new file mode 100644
index 0000000000..7466374129
--- /dev/null
+++ b/demos/2d/shower_of_bullets/bullet.png
Binary files differ
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
new file mode 100644
index 0000000000..6ed643b62d
--- /dev/null
+++ b/demos/2d/shower_of_bullets/face_happy.png
Binary files differ
diff --git a/demos/2d/shower_of_bullets/face_sad.png b/demos/2d/shower_of_bullets/face_sad.png
new file mode 100644
index 0000000000..d6318b20a3
--- /dev/null
+++ b/demos/2d/shower_of_bullets/face_sad.png
Binary files differ
diff --git a/demos/2d/shower_of_bullets/icon.png b/demos/2d/shower_of_bullets/icon.png
new file mode 100644
index 0000000000..432c74a5a3
--- /dev/null
+++ b/demos/2d/shower_of_bullets/icon.png
Binary files differ
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
new file mode 100644
index 0000000000..648888d099
--- /dev/null
+++ b/demos/2d/shower_of_bullets/shower.scn
Binary files differ
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/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
new file mode 100644
index 0000000000..73df340b1e
--- /dev/null
+++ b/demos/3d/navmesh/navmesh.scn
Binary files differ
diff --git a/demos/3d/navmesh/particle.png b/demos/3d/navmesh/particle.png
new file mode 100644
index 0000000000..18851c8c9d
--- /dev/null
+++ b/demos/3d/navmesh/particle.png
Binary files differ
diff --git a/demos/3d/platformer/texture.tex b/demos/3d/platformer/texture.tex
index 24c4607ab1..d9181b7ffa 100644
--- a/demos/3d/platformer/texture.tex
+++ b/demos/3d/platformer/texture.tex
Binary files differ
diff --git a/demos/3d/platformer/tiles.res b/demos/3d/platformer/tiles.res
index 53534788a1..d4fb779ff1 100644
--- a/demos/3d/platformer/tiles.res
+++ b/demos/3d/platformer/tiles.res
Binary files differ
diff --git a/demos/3d/truck_town/car_base.scn b/demos/3d/truck_town/car_base.scn
new file mode 100644
index 0000000000..d62c8dcb29
--- /dev/null
+++ b/demos/3d/truck_town/car_base.scn
Binary files differ
diff --git a/demos/3d/truck_town/car_select.gd b/demos/3d/truck_town/car_select.gd
new file mode 100644
index 0000000000..00b4d853b8
--- /dev/null
+++ b/demos/3d/truck_town/car_select.gd
@@ -0,0 +1,42 @@
+
+extends Control
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+func _ready():
+ # Initalization here
+ pass
+
+var town=null
+
+
+func _back():
+
+ town.queue_free()
+ show()
+
+
+func _load_scene(car):
+
+ var tt = load(car).instance()
+ tt.set_name("car")
+ town = load("res://truck_scene.scn").instance()
+ town.get_node("instance_pos").add_child(tt)
+ town.get_node("back").connect("pressed",self,"_back")
+ get_parent().add_child(town)
+ hide()
+
+func _on_van_1_pressed():
+
+ _load_scene("res://car_base.scn")
+
+
+func _on_van_2_pressed():
+
+ _load_scene("res://trailer_truck.scn")
+
+
+func _on_van_3_pressed():
+ _load_scene("res://crane.scn")
diff --git a/demos/3d/truck_town/car_select.scn b/demos/3d/truck_town/car_select.scn
new file mode 100644
index 0000000000..024adf1423
--- /dev/null
+++ b/demos/3d/truck_town/car_select.scn
Binary files differ
diff --git a/demos/3d/truck_town/cement.tex b/demos/3d/truck_town/cement.tex
new file mode 100644
index 0000000000..a80cde6464
--- /dev/null
+++ b/demos/3d/truck_town/cement.tex
Binary files differ
diff --git a/demos/3d/truck_town/choose_tow.png b/demos/3d/truck_town/choose_tow.png
new file mode 100644
index 0000000000..8f92833450
--- /dev/null
+++ b/demos/3d/truck_town/choose_tow.png
Binary files differ
diff --git a/demos/3d/truck_town/choose_trailer.png b/demos/3d/truck_town/choose_trailer.png
new file mode 100644
index 0000000000..ead3330296
--- /dev/null
+++ b/demos/3d/truck_town/choose_trailer.png
Binary files differ
diff --git a/demos/3d/truck_town/choose_van.png b/demos/3d/truck_town/choose_van.png
new file mode 100644
index 0000000000..1ecdd54372
--- /dev/null
+++ b/demos/3d/truck_town/choose_van.png
Binary files differ
diff --git a/demos/3d/truck_town/crane.scn b/demos/3d/truck_town/crane.scn
new file mode 100644
index 0000000000..2c4645af69
--- /dev/null
+++ b/demos/3d/truck_town/crane.scn
Binary files differ
diff --git a/demos/3d/truck_town/engine.cfg b/demos/3d/truck_town/engine.cfg
new file mode 100644
index 0000000000..f47c0de4fa
--- /dev/null
+++ b/demos/3d/truck_town/engine.cfg
@@ -0,0 +1,12 @@
+[application]
+
+main_scene="res://car_select.scn"
+
+[display]
+
+width=1280
+height=720
+
+[rasterizer]
+
+shadow_filter=3
diff --git a/demos/3d/truck_town/follow_camera.gd b/demos/3d/truck_town/follow_camera.gd
new file mode 100644
index 0000000000..cf7172d7bb
--- /dev/null
+++ b/demos/3d/truck_town/follow_camera.gd
@@ -0,0 +1,69 @@
+
+extends Camera
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+var collision_exception=[]
+export var min_distance=0.5
+export var max_distance=4.0
+export var angle_v_adjust=0.0
+export var autoturn_ray_aperture=25
+export var autoturn_speed=50
+var max_height = 2.0
+var min_height = 0
+
+func _fixed_process(dt):
+ var target = get_parent().get_global_transform().origin
+ var pos = get_global_transform().origin
+ var up = Vector3(0,1,0)
+
+ var delta = pos - target
+
+ #regular delta follow
+
+ #check ranges
+
+ if (delta.length() < min_distance):
+ delta = delta.normalized() * min_distance
+ elif (delta.length() > max_distance):
+ delta = delta.normalized() * max_distance
+
+ #check upper and lower height
+ if ( delta.y > max_height):
+ delta.y = max_height
+ if ( delta.y < min_height):
+ delta.y = min_height
+
+ pos = target + delta
+
+ look_at_from_pos(pos,target,up)
+
+ #turn a little up or down
+ var t = get_transform()
+ t.basis = Matrix3(t.basis[0],deg2rad(angle_v_adjust)) * t.basis
+ set_transform(t)
+
+
+
+func _ready():
+
+#find collision exceptions for ray
+ var node = self
+ while(node):
+ if (node extends RigidBody):
+ collision_exception.append(node.get_rid())
+ break
+ else:
+ node=node.get_parent()
+ # Initalization here
+ set_fixed_process(true)
+ #this detaches the camera transform from the parent spatial node
+ set_as_toplevel(true)
+
+
+
+
+
+
diff --git a/demos/3d/truck_town/grass.tex b/demos/3d/truck_town/grass.tex
new file mode 100644
index 0000000000..c28d060697
--- /dev/null
+++ b/demos/3d/truck_town/grass.tex
Binary files differ
diff --git a/demos/3d/truck_town/trailer_truck.scn b/demos/3d/truck_town/trailer_truck.scn
new file mode 100644
index 0000000000..0131e9e3a2
--- /dev/null
+++ b/demos/3d/truck_town/trailer_truck.scn
Binary files differ
diff --git a/demos/3d/truck_town/truck_scene.scn b/demos/3d/truck_town/truck_scene.scn
new file mode 100644
index 0000000000..a02ce259c1
--- /dev/null
+++ b/demos/3d/truck_town/truck_scene.scn
Binary files differ
diff --git a/demos/3d/truck_town/trucktown.scn b/demos/3d/truck_town/trucktown.scn
new file mode 100644
index 0000000000..57a84315ee
--- /dev/null
+++ b/demos/3d/truck_town/trucktown.scn
Binary files differ
diff --git a/demos/3d/truck_town/vehicle.gd b/demos/3d/truck_town/vehicle.gd
new file mode 100644
index 0000000000..1aa7f0faa2
--- /dev/null
+++ b/demos/3d/truck_town/vehicle.gd
@@ -0,0 +1,54 @@
+
+extends VehicleBody
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+
+const STEER_SPEED=1
+const STEER_LIMIT=0.4
+
+var steer_angle=0
+var steer_target=0
+
+
+export var engine_force=40
+
+func _fixed_process(delta):
+
+
+ if (Input.is_action_pressed("ui_left")):
+ steer_target=-STEER_LIMIT
+ elif (Input.is_action_pressed("ui_right")):
+ steer_target=STEER_LIMIT
+ else:
+ steer_target=0
+
+ if (Input.is_action_pressed("ui_up")):
+ set_engine_force(engine_force)
+ else:
+ set_engine_force(0)
+
+ if (Input.is_action_pressed("ui_down")):
+ set_brake(1)
+ else:
+ set_brake(0.0)
+
+
+ if (steer_target < steer_angle):
+ steer_angle -= STEER_SPEED*delta
+ if (steer_target > steer_angle):
+ steer_angle=steer_target
+ elif (steer_target > steer_angle):
+ steer_angle += STEER_SPEED*delta
+ if (steer_target < steer_angle):
+ steer_angle=steer_target
+
+ set_steering(steer_angle)
+func _ready():
+ # Initalization here
+ set_fixed_process(true)
+ pass
+
+
diff --git a/demos/misc/autoload/global.gd b/demos/misc/autoload/global.gd
index dca661a31a..a0415c6ee0 100644
--- a/demos/misc/autoload/global.gd
+++ b/demos/misc/autoload/global.gd
@@ -9,20 +9,15 @@ func goto_scene(scene):
var s = ResourceLoader.load(scene)
#queue erasing old (don't use free because that scene is calling this method)
current_scene.queue_free()
- # Remove the scene before loading the previous one.
- # The node is removed when deleted anyway, but this will fix issues that
- # might arise if both have a root node with the same name,
- # as adding both together will cause the second to be renamed. (not usually a problem, but you might be wanting to look for the node later and not find it)
- get_scene().get_root().remove(current_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
new file mode 100644
index 0000000000..3e991fcc29
--- /dev/null
+++ b/demos/misc/tween/icon.png
Binary files differ
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
new file mode 100644
index 0000000000..efa4b799a0
--- /dev/null
+++ b/demos/misc/udp_chat/chat.scn
Binary files differ
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
new file mode 100644
index 0000000000..db6e21cce1
--- /dev/null
+++ b/demos/misc/udp_chat/icon.png
Binary files differ
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 527991d147..35de0106b5 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -9,271 +9,271 @@
</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="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>
<description>
</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>
</description>
@@ -297,18 +297,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 +318,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.
@@ -538,6 +538,14 @@
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>
+ </description>
+ </method>
<method name="print_stack" >
<return type="Nil">
</return>
@@ -549,7 +557,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 +576,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 +1424,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 +1585,7 @@
</description>
</method>
<method name="get_area" >
- <return type="real">
+ <return type="float">
</return>
<description>
Get the area inside the [AABB]
@@ -1617,7 +1616,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 +1639,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 +1659,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 +1717,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 +1753,6 @@
<member name="size" type="Vector3">
</member>
<member name="end" type="Vector3">
- Same as pos+size.
</member>
</members>
<constants>
@@ -1792,7 +1800,11 @@
<method name="add_button" >
<return type="Button">
</return>
- <argument index="0" name="text" type="String" default="&quot;&quot;">
+ <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="&quot;&quot;">
</argument>
<description>
</description>
@@ -1933,7 +1945,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 +1973,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 +2094,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 +2109,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 +2131,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 +2153,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 +2161,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 +2191,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 +2206,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 +2237,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 +2266,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 +2279,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 +2310,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 +2338,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 +2392,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 +2441,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 +2459,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 +2475,9 @@
<method name="play" >
<argument index="0" name="name" type="String" default="&quot;&quot;">
</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 +2547,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 +2591,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 +2603,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 +2638,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 +2646,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 +2679,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 +2747,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 +2794,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 +2810,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 +2834,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 +2842,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 +2856,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 +2864,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 +2904,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 +2920,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 +2946,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 +2978,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 +2994,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 +3046,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 +3234,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 +3281,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 +3377,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 +3424,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 +3857,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 +3866,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 +3881,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 +3894,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 +3905,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 +3930,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 +3939,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 +3948,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 +3957,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 +3975,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 +3984,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 +3993,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 +4011,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 +4052,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 +4205,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 +4272,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 +4393,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 +4783,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 +4831,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 +4858,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 +5051,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 +5301,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 +5346,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 +5417,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 +5437,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 +5552,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 +5578,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 +5619,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 +5674,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 +5752,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 +5797,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 +5815,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 +5876,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 +5887,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 +5898,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 +5924,7 @@
</description>
</method>
<method name="draw_char" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="font" type="Font">
</argument>
@@ -5462,7 +5943,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 +5987,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 +6023,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 +6093,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 +6147,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 +6187,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 +6218,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 +6253,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 +6293,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 +6316,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 +6402,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 +6433,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 +6558,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 +6662,7 @@
</description>
</method>
<method name="gray" >
- <return type="real">
+ <return type="float">
</return>
<description>
Convert the color to gray.
@@ -6277,7 +6680,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 +6710,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 +6749,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 +6883,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 +6937,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 +7014,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 +7291,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 +7302,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 +7350,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 +7478,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 +7773,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 +7969,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 +8029,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 +8093,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>
- <description>
- </description>
- </method>
- <method name="set_points_in" >
- <argument index="0" name="arg0" type="Vector2Array">
+ <argument index="0" name="fofs" type="float">
</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 +8187,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 +8243,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 +8251,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 +8277,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 +8309,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 +8466,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 +8485,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 +8585,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 +8631,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 +8959,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_GLOW" value="0">
+ <constant name="FX_BCS" value="6">
</constant>
- <constant name="FX_DOF_BLUR" value="1">
+ <constant name="FX_SRGB" value="7">
</constant>
- <constant name="FX_HDR" value="2">
+ <constant name="FX_MAX" value="8">
</constant>
- <constant name="FX_FOG" value="3">
+ <constant name="FX_BLUR_BLEND_MODE_ADDITIVE" value="0">
</constant>
- <constant name="FX_BCS" value="4">
+ <constant name="FX_BLUR_BLEND_MODE_SCREEN" value="1">
</constant>
- <constant name="FX_GAMMA" value="5">
+ <constant name="FX_BLUR_BLEND_MODE_SOFTLIGHT" value="2">
</constant>
- <constant name="FX_MAX" value="6">
+ <constant name="FX_HDR_TONE_MAPPER_LINEAR" value="0">
</constant>
- <constant name="FX_PARAM_GLOW_BLUR_PASSES" value="0">
+ <constant name="FX_HDR_TONE_MAPPER_LOG" value="1">
</constant>
- <constant name="FX_PARAM_GLOW_BLOOM" value="1">
+ <constant name="FX_HDR_TONE_MAPPER_REINHARDT" value="2">
</constant>
- <constant name="FX_PARAM_GLOW_BLOOM_TRESHOLD" value="2">
+ <constant name="FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE" value="3">
</constant>
- <constant name="FX_PARAM_DOF_BLUR_PASSES" value="3">
+ <constant name="FX_PARAM_AMBIENT_LIGHT_COLOR" value="0">
</constant>
- <constant name="FX_PARAM_DOF_BLUR_BEGIN" value="4">
+ <constant name="FX_PARAM_AMBIENT_LIGHT_ENERGY" value="1">
</constant>
- <constant name="FX_PARAM_DOF_BLUR_RANGE" value="5">
+ <constant name="FX_PARAM_GLOW_BLUR_PASSES" value="2">
</constant>
- <constant name="FX_PARAM_HDR_EXPOSURE" value="6">
+ <constant name="FX_PARAM_GLOW_BLUR_SCALE" value="3">
</constant>
- <constant name="FX_PARAM_HDR_SCALAR" value="7">
+ <constant name="FX_PARAM_GLOW_BLUR_STRENGTH" value="4">
</constant>
- <constant name="FX_PARAM_HDR_GLOW_TRESHOLD" value="8">
+ <constant name="FX_PARAM_GLOW_BLUR_BLEND_MODE" value="5">
</constant>
- <constant name="FX_PARAM_HDR_GLOW_SCALE" value="9">
+ <constant name="FX_PARAM_GLOW_BLOOM" value="6">
</constant>
- <constant name="FX_PARAM_HDR_MIN_LUMINANCE" value="10">
+ <constant name="FX_PARAM_GLOW_BLOOM_TRESHOLD" value="7">
</constant>
- <constant name="FX_PARAM_HDR_MAX_LUMINANCE" value="11">
+ <constant name="FX_PARAM_DOF_BLUR_PASSES" value="8">
</constant>
- <constant name="FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED" value="12">
+ <constant name="FX_PARAM_DOF_BLUR_BEGIN" value="9">
</constant>
- <constant name="FX_PARAM_FOG_BEGIN" value="13">
+ <constant name="FX_PARAM_DOF_BLUR_RANGE" value="10">
</constant>
- <constant name="FX_PARAM_FOG_ATTENUATION" value="16">
+ <constant name="FX_PARAM_HDR_TONEMAPPER" value="11">
</constant>
- <constant name="FX_PARAM_FOG_BEGIN_COLOR" value="14">
+ <constant name="FX_PARAM_HDR_EXPOSURE" value="12">
</constant>
- <constant name="FX_PARAM_FOG_END_COLOR" value="15">
+ <constant name="FX_PARAM_HDR_WHITE" value="13">
</constant>
- <constant name="FX_PARAM_FOG_BG" value="17">
+ <constant name="FX_PARAM_HDR_GLOW_TRESHOLD" value="14">
</constant>
- <constant name="FX_PARAM_BCS_BRIGHTNESS" value="18">
+ <constant name="FX_PARAM_HDR_GLOW_SCALE" value="15">
</constant>
- <constant name="FX_PARAM_BCS_CONTRAST" value="19">
+ <constant name="FX_PARAM_HDR_MIN_LUMINANCE" value="16">
</constant>
- <constant name="FX_PARAM_BCS_SATURATION" value="20">
+ <constant name="FX_PARAM_HDR_MAX_LUMINANCE" value="17">
</constant>
- <constant name="FX_PARAM_GAMMA" value="21">
+ <constant name="FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED" value="18">
</constant>
- <constant name="FX_PARAM_MAX" value="22">
+ <constant name="FX_PARAM_FOG_BEGIN" value="19">
+ </constant>
+ <constant name="FX_PARAM_FOG_ATTENUATION" value="22">
+ </constant>
+ <constant name="FX_PARAM_FOG_BEGIN_COLOR" value="20">
+ </constant>
+ <constant name="FX_PARAM_FOG_END_COLOR" value="21">
+ </constant>
+ <constant name="FX_PARAM_FOG_BG" value="23">
+ </constant>
+ <constant name="FX_PARAM_BCS_BRIGHTNESS" value="24">
+ </constant>
+ <constant name="FX_PARAM_BCS_CONTRAST" value="25">
+ </constant>
+ <constant name="FX_PARAM_BCS_SATURATION" value="26">
+ </constant>
+ <constant name="FX_PARAM_MAX" value="27">
</constant>
</constants>
</class>
@@ -8559,13 +9060,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 +9110,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 +9170,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 +9196,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 +9210,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 +9253,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 +9352,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 +9442,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 +9648,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 +9745,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 +9814,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 +9827,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 +9899,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 +9946,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 +10014,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 +10064,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 +10225,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 +10239,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 +10253,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 +10261,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 +10318,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 +10363,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 +10375,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 +10402,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 +10453,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 +10504,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 +10608,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 +10641,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 +10677,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 +10792,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 +10845,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 +10890,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 +10921,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 +10963,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 +10979,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 +11013,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 +11043,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 +11061,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 +11087,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 +11111,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 +11200,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 +11262,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 +11364,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 +11481,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 +11561,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 +11639,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 +11663,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 +11729,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 +11792,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 +11807,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 +11827,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 +11940,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 +11949,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 +11996,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 +12193,7 @@
</member>
<member name="pressed" type="bool">
</member>
- <member name="pressure" type="real">
+ <member name="pressure" type="float">
</member>
</members>
<constants>
@@ -11480,7 +12253,7 @@
</member>
<member name="axis" type="int">
</member>
- <member name="value" type="real">
+ <member name="value" type="float">
</member>
</members>
<constants>
@@ -11722,9 +12495,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 +12559,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 +12635,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 +12673,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 +12838,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 +12871,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 +12954,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 +13159,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 +13218,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 +13334,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 +13372,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 +13394,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 +13403,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 +13466,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 +13531,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 +13583,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 +13692,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 +13719,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 +13763,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 +13804,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 +13819,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 +13874,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 +13888,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 +13930,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 name="DEPTH_DRAW_ALWAYS" value="0">
</constant>
- <constant name="SHADE_MODEL_CUSTOM_0" value="4">
+ <constant name="DEPTH_DRAW_OPAQUE_ONLY" value="1">
</constant>
- <constant name="SHADE_MODEL_CUSTOM_1" value="5">
+ <constant name="DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA" value="2">
</constant>
- <constant name="SHADE_MODEL_CUSTOM_2" value="6">
- </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 +13954,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 +13969,7 @@
</description>
<methods>
<method name="determinant" >
- <return type="real">
+ <return type="float">
</return>
<description>
Return the determinant of the matrix.
@@ -12875,6 +13988,12 @@
<description>
</description>
</method>
+ <method name="get_scale" >
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="inverse" >
<return type="Matrix3">
</return>
@@ -12894,7 +14013,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 +14029,7 @@
</description>
</method>
<method name="tdotx" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="with" type="Vector3">
</argument>
@@ -12919,7 +14038,7 @@
</description>
</method>
<method name="tdoty" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="with" type="Vector3">
</argument>
@@ -12928,7 +14047,7 @@
</description>
</method>
<method name="tdotz" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="with" type="Vector3">
</argument>
@@ -12975,7 +14094,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 +14133,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 +14156,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 +14172,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 +14192,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 +14241,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 +14275,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 +14443,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 +14864,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 +15138,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 +15323,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 +15498,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 +15521,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 +15616,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 +15656,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 +15729,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 +15800,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 +15821,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 +15862,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 +15903,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 +15925,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 +16001,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 +16022,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 +16035,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 +16064,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 +16258,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 +16325,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 +16348,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 +16485,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 +16548,7 @@
</description>
</method>
<method name="get_frames_per_second" qualifiers="const" >
- <return type="real">
+ <return type="float">
</return>
<description>
</description>
@@ -15118,11 +16557,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 +16591,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 +16665,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 +16880,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 +16942,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 +17179,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 +17354,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 +17388,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 +17464,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 +17484,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 +17612,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 +17802,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 +17820,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 +17838,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 +17886,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 +17996,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 +18046,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 +18062,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 +18123,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 +18190,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 +18204,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 +18234,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 +18275,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 +18338,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 +18433,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 +18587,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 +18638,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 +18670,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 +18705,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 +18824,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 +18840,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 +18881,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]
@@ -17155,36 +18906,56 @@
</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 +19023,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 +19087,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 +19288,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 +19326,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 +19400,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 +19557,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 +19619,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 +19642,7 @@
<description>
</description>
</method>
- <method name="free" >
+ <method name="free_rid" >
<argument index="0" name="rid" type="RID">
</argument>
<description>
@@ -17829,6 +19654,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 +19746,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 +19764,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 +19920,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 +19954,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 +19995,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 +20056,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 +20155,7 @@
</description>
</method>
<method name="get_step" qualifiers="const" >
- <return type="real">
+ <return type="float">
</return>
<description>
</description>
@@ -18196,33 +20191,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>
- <argument index="2" name="result_max" type="int">
+ <description>
+ </description>
+ </method>
+ <method name="cast_motion" >
+ <return type="Array">
+ </return>
+ <argument index="0" name="shape" type="PhysicsShapeQueryParameters">
+ </argument>
+ <argument index="1" name="motion" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="collide_shape" >
+ <return type="Array">
+ </return>
+ <argument index="0" name="shape" type="PhysicsShapeQueryParameters">
</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="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 +20323,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 +20387,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 +20456,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 +20516,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 +20685,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 +20700,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 +20736,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 +20812,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 +21114,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 +21316,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 +21334,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 +21471,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 +21530,7 @@
</description>
</method>
<method name="distance_to" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="point" type="Vector3">
</argument>
@@ -18937,7 +21548,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 +21613,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 +21637,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 +21646,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 +21680,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 +21914,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 +21945,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 +21958,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 +22032,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 +22251,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 +22292,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 +22335,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 +22363,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 +22412,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 +22569,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 +22591,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 +22616,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 +22627,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 +22652,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 +22695,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 +22749,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 +22825,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 +23028,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 +23079,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 +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>
@@ -20194,7 +23127,7 @@
</description>
<methods>
<method name="get" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="idx" type="int">
</argument>
@@ -20202,7 +23135,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 +23149,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 +23201,7 @@
</description>
</method>
<method name="get_area" >
- <return type="real">
+ <return type="float">
</return>
<description>
</description>
@@ -20276,7 +23209,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 +23253,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 +23343,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 +23431,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 +23779,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 +23927,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 +23990,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 +24030,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 +24163,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 +24187,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 +24287,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 +24357,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 +24452,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 +24478,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 +24806,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 +24822,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 +24907,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 +24916,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 +24925,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 +24933,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 +24948,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 +24961,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 +24972,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 +24988,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 +24997,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 +25006,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 +25014,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 +25023,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 +25032,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 +25050,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 +25059,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 +25068,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 +25076,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 +25085,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 +25094,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 +25103,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 +25133,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 +25151,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 +25199,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 +25338,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 +25347,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 +25375,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,87 +25395,10 @@
</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">
- <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">
+<class name="SceneTree" 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" >
@@ -22479,7 +25409,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 +25421,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 +25429,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 +25441,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 +25493,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 +25533,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 +25642,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 +25810,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 +25831,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 +25873,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 +25910,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 +25964,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 +26105,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 +26191,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 +26274,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 +26312,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 +26472,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 +26507,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 +26520,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 +26596,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 +26604,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 +26734,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 +26756,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 +26829,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 +27064,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 +27363,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 +27387,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 +27433,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 +27447,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 +27529,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="&quot;&quot;">
+ </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 +27601,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 +27625,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 +27694,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 +27730,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 +27754,7 @@
</description>
</method>
<method name="get_length" qualifiers="const" >
- <return type="real">
+ <return type="float">
</return>
<description>
</description>
@@ -24600,6 +27964,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 +28122,7 @@
</description>
</method>
<method name="to_float" >
- <return type="real">
+ <return type="float">
</return>
<description>
</description>
@@ -24863,14 +28239,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 +28255,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 +28430,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 +28472,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 +28488,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 +28579,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 +28599,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 +28766,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 +28863,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 +28882,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 +29084,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 +29207,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 +29352,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 +29881,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 +29973,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 +30062,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 +30286,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 +30338,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 +30441,11 @@
</method>
</methods>
<signals>
- <signal name="pressed">
+ <signal name="released">
<description>
</description>
</signal>
- <signal name="released">
+ <signal name="pressed">
<description>
</description>
</signal>
@@ -26899,7 +30495,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 +30636,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 +30685,10 @@
<description>
</description>
</method>
+ <method name="clear" >
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
@@ -27310,6 +30916,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 +31082,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 +31098,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 +31357,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 +31776,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 +31792,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 +31825,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 +31855,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 +31873,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 +31897,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 +31916,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 +31946,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 +31960,7 @@
</description>
</method>
<method name="distance_to" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="to" type="Vector2">
</argument>
@@ -27855,7 +31969,7 @@
</description>
</method>
<method name="dot" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="with" type="Vector2">
</argument>
@@ -27877,20 +31991,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 +32014,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 +32028,7 @@
</description>
</method>
<method name="reflect" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="vec" type="Vector2">
</argument>
@@ -27924,13 +32038,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 +32066,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 +32169,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 +32185,7 @@
</description>
</method>
<method name="distance_to" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="b" type="Vector3">
</argument>
@@ -28080,7 +32194,7 @@
</description>
</method>
<method name="dot" >
- <return type="real">
+ <return type="float">
</return>
<argument index="0" name="b" type="Vector3">
</argument>
@@ -28096,14 +32210,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 +32228,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 +32253,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 +32282,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 +32366,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 +32611,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 +32640,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 +32674,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 +32687,8 @@
</description>
</method>
<method name="pop_frame" >
- <return type="Image">
- </return>
+ <argument index="0" name="arg0" type="Object">
+ </argument>
<description>
</description>
</method>
@@ -28368,16 +32698,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 +32866,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 +32920,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 +32939,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 +32997,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 +33021,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 +33423,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 +33673,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 +33693,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 +33729,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 +33805,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 +33935,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 +34055,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 +34093,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 +34105,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 +34333,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 +34419,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 +34437,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 +34461,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 +34523,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 +34553,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 +34598,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 +34617,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 +34634,10 @@
<description>
</description>
</method>
+ <method name="flush" >
+ <description>
+ </description>
+ </method>
<method name="free" >
<argument index="0" name="arg0" type="RID">
</argument>
@@ -30196,7 +34678,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 +34708,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 +34828,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 +34842,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 +34854,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 +34918,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 +35173,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 +35210,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 +35225,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 +35253,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 b50c5afbf2..46334468ba 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -7,6 +7,7 @@ Export('env')
SConscript('unix/SCsub');
SConscript('alsa/SCsub');
+SConscript('pulseaudio/SCsub');
SConscript('windows/SCsub');
SConscript('gles2/SCsub');
SConscript('gles1/SCsub');
@@ -82,7 +83,7 @@ if len(list) > 0:
drivers_base=[]
env.add_source_files(drivers_base,"*.cpp")
-lib_list.insert(0, env.Library("drivers", drivers_base, LIBSUFFIX=env['platform_libsuffix']))
+lib_list.insert(0, env.Library("drivers", drivers_base))
env.Prepend(LIBS=lib_list)
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/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 ecf80047bd..9375532f07 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -63,6 +63,13 @@
#define _glClearDepth glClearDepthf
#endif
+
+#define _GL_SRGB_EXT 0x8C40
+#define _GL_SRGB_ALPHA_EXT 0x8C42
+
+#define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+
//#define DEBUG_OPENGL
#ifdef DEBUG_OPENGL
@@ -132,11 +139,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
{
@@ -303,9 +312,23 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c
#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_SRGB_PVRTC_2BPPV1_EXT 0x8A54
+#define _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
+#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
+#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
+
+
#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_LUMINANCE_LATC1_EXT 0x8C70
+#define _EXT_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define _EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define _EXT_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+
+
#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB
#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB
#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
@@ -316,6 +339,22 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c
#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
#define _EXT_ETC1_RGB8_OES 0x8D64
+
+
+#define _EXT_SLUMINANCE_NV 0x8C46
+#define _EXT_SLUMINANCE_ALPHA_NV 0x8C44
+#define _EXT_SRGB8_NV 0x8C41
+#define _EXT_SLUMINANCE8_NV 0x8C47
+#define _EXT_SLUMINANCE8_ALPHA8_NV 0x8C45
+
+
+#define _EXT_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C
+#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
+#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
+#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
+
+
+
#define _EXT_ATC_RGB_AMD 0x8C92
#define _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
#define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
@@ -323,10 +362,11 @@ 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) {
@@ -334,6 +374,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
case Image::FORMAT_GRAYSCALE: {
r_gl_components=1;
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: {
@@ -342,6 +383,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
image.convert(Image::FORMAT_RGBA);
r_gl_components=4;
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: {
@@ -349,6 +391,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
//image.convert(Image::FORMAT_RGBA);
r_gl_components=2;
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;
@@ -358,6 +401,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
image.convert(Image::FORMAT_RGB);
r_gl_components=3;
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;
@@ -366,54 +410,119 @@ 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=GL_RGBA;
+
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} break;
case Image::FORMAT_RGB: {
r_gl_components=3;
- r_gl_format=GL_RGB;
+
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGB;
+ }
} break;
case Image::FORMAT_RGBA: {
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
+
r_has_alpha_cache=true;
} break;
case Image::FORMAT_BC1: {
- if (!s3tc_supported) {
+ if (!s3tc_supported || (!s3tc_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
if (!image.empty()) {
image.decompress();
}
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
r_gl_components=1; //doesn't matter much
- r_gl_format=_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;
};
} break;
case Image::FORMAT_BC2: {
- if (!s3tc_supported) {
+ if (!s3tc_supported || (!s3tc_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
if (!image.empty()) {
image.decompress();
}
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
r_gl_components=1; //doesn't matter much
- r_gl_format=_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;
};
@@ -421,18 +530,30 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
} break;
case Image::FORMAT_BC3: {
- if (!s3tc_supported) {
+ if (!s3tc_supported || (!s3tc_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
if (!image.empty()) {
image.decompress();
}
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
r_gl_components=1; //doesn't matter much
- r_gl_format=_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;
};
@@ -440,18 +561,30 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
} break;
case Image::FORMAT_BC4: {
- if (!s3tc_supported) {
+ if (!latc_supported) {
if (!image.empty()) {
image.decompress();
}
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_EXT_COMPRESSED_RED_RGTC1;
+ r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT;
r_gl_components=1; //doesn't matter much
r_compressed=true;
};
@@ -459,36 +592,60 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
} break;
case Image::FORMAT_BC5: {
- if (!s3tc_supported) {
+ if (!latc_supported ) {
if (!image.empty()) {
image.decompress();
}
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_EXT_COMPRESSED_RG_RGTC2;
+ r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
r_gl_components=1; //doesn't matter much
r_compressed=true;
};
} break;
case Image::FORMAT_PVRTC2: {
- if (!pvr_supported) {
+ if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
if (!image.empty()) {
image.decompress();
}
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_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;
@@ -497,18 +654,31 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
} break;
case Image::FORMAT_PVRTC2_ALPHA: {
- if (!pvr_supported) {
+ if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
if (!image.empty())
image.decompress();
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_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;
@@ -517,16 +687,28 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
} break;
case Image::FORMAT_PVRTC4: {
- if (!pvr_supported) {
+ if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
if (!image.empty())
image.decompress();
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_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;
}
@@ -534,16 +716,28 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
} break;
case Image::FORMAT_PVRTC4_ALPHA: {
- if (!pvr_supported) {
+ if (!pvr_supported || (!pvr_srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
if (!image.empty())
image.decompress();
r_gl_components=4;
- r_gl_format=GL_RGBA;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_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;
}
@@ -551,18 +745,31 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
} break;
case Image::FORMAT_ETC: {
- if (!etc_supported) {
+ if (!etc_supported || p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
if (!image.empty()) {
image.decompress();
}
r_gl_components=3;
- r_gl_format=GL_RGB;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ 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_internal_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;
}
@@ -576,12 +783,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;
}
@@ -595,12 +802,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;
}
@@ -614,12 +821,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;
}
@@ -630,7 +837,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;
@@ -641,6 +848,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;
}
@@ -672,6 +883,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);
@@ -690,7 +902,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);
@@ -708,6 +920,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
@@ -722,7 +935,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;
@@ -740,6 +953,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;
@@ -747,7 +961,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()) {
@@ -757,7 +971,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;
}
@@ -800,6 +1014,16 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
}
+ if (use_anisotropic_filter) {
+
+ if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) {
+
+ glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_level);
+ } else {
+ glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
+ }
+ }
+
int mipmaps= (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1;
@@ -821,7 +1045,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) {
glTexSubImage2D( blit_target, i, 0,0,w,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, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]);
}
}
@@ -1047,6 +1271,16 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) {
}
+ if (use_anisotropic_filter) {
+
+ if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) {
+
+ glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_level);
+ } else {
+ glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
+ }
+ }
+
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
@@ -1177,6 +1411,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;
@@ -1188,6 +1425,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);
@@ -1307,6 +1547,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 */
@@ -1349,6 +1631,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 {
@@ -1356,6 +1639,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
}
@@ -1387,7 +1671,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();
@@ -1399,6 +1683,7 @@ void RasterizerGLES2::material_set_flag(RID p_material, VS::MaterialFlag p_flag,
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;
}
@@ -3940,6 +4225,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);
@@ -3949,10 +4237,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
@@ -4155,6 +4457,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);
@@ -4164,9 +4473,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
+ }
}
@@ -4179,6 +4495,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
@@ -4212,7 +4533,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
enablers.push_back("#define ENABLE_UV_INTERP\n");
if (fragment_flags.use_uv2_interp || vertex_flags.use_uv2_interp)
enablers.push_back("#define ENABLE_UV2_INTERP\n");
- if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp)
+ if (fragment_flags.use_tangent_interp || vertex_flags.use_tangent_interp || fragment_flags.uses_normalmap)
enablers.push_back("#define ENABLE_TANGENT_INTERP\n");
if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp)
enablers.push_back("#define ENABLE_VAR1_INTERP\n");
@@ -4227,6 +4548,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
if (fragment_flags.uses_discard) {
enablers.push_back("#define ENABLE_DISCARD\n");
}
+ if (fragment_flags.uses_normalmap) {
+ enablers.push_back("#define ENABLE_NORMALMAP\n");
+ }
if (light_flags.uses_light) {
enablers.push_back("#define USE_LIGHT_SHADER_CODE\n");
}
@@ -4236,7 +4560,36 @@ 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");
+ }
+
+ 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);
}
@@ -4247,7 +4600,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++;
}
@@ -4394,7 +4749,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) {
@@ -4597,31 +4953,46 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_
Material::UniformData ud;
- bool keep=true;
+ bool keep=true; //keep material value
+ bool has_old = old_mparams.has(E->key());
+ bool old_inuse=has_old && old_mparams[E->key()].inuse;
- 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()) {
-
- if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) {
+ //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;*/
+
+ //value is invalid because type differs and default is not null
+ if (E->value().default_value.get_type()!=Variant::NIL)
keep=false;
}
+ ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP);
+
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;
}
@@ -4656,6 +5027,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF13);
material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM);
material_shader.set_conditional(MaterialShaderGLES2::USE_LIGHTMAP_ON_UV2,p_material->flags[VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2]);
+ material_shader.set_conditional(MaterialShaderGLES2::USE_COLOR_ATTRIB_SRGB_TO_LINEAR,p_material->flags[VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB] && current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]);
if (p_opaque_pass && p_material->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA && p_material->shader_cache && p_material->shader_cache->has_alpha) {
@@ -4735,12 +5107,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) {
@@ -4764,8 +5138,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);
@@ -4897,7 +5273,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);
@@ -4908,7 +5284,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]));
@@ -4952,7 +5328,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) {
}
-template<bool USE_NORMAL, bool USE_TANGENT>
+template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE>
void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms) {
uint32_t basesize = 3;
@@ -4962,6 +5338,8 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str
basesize+=4;
uint32_t extra=(p_dst_stride-basesize*4);
+ const int dstvec_size=3+(USE_NORMAL?3:0)+(USE_TANGENT?4:0);
+ float dstcopy[dstvec_size];
for(int i=0;i<p_elements;i++) {
@@ -4970,7 +5348,11 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str
const uint16_t *bi = (const uint16_t*)&p_src_bones[ss];
const float *bw = (const float *)&p_src_weights[ss];
const float *src_vec=(const float *)&p_src_array[ss];
- float *dst_vec=(float*)&p_dst_array[ds];
+ float *dst_vec;
+ if (INPLACE)
+ dst_vec=dstcopy;
+ else
+ dst_vec=(float*)&p_dst_array[ds];
dst_vec[0]=0.0;
dst_vec[1]=0.0;
@@ -5023,16 +5405,28 @@ void RasterizerGLES2::_skeleton_xform(const uint8_t * p_src_array, int p_src_str
end:
- //copy extra stuff
- const uint8_t *esp =(const uint8_t*) &src_vec[basesize];
- uint8_t *edp =(uint8_t*) &dst_vec[basesize];
+ if (INPLACE) {
+ const uint8_t *esp =(const uint8_t*) dstcopy;
+ uint8_t *edp =(uint8_t*)&p_dst_array[ds];
- for(uint32_t j=0;j<extra;j++) {
- edp[j]=esp[j];
- }
+ for(uint32_t j=0;j<dstvec_size*4;j++) {
+
+ edp[j]=esp[j];
+ }
+
+ } else {
+ //copy extra stuff
+ const uint8_t *esp =(const uint8_t*) &src_vec[basesize];
+ uint8_t *edp =(uint8_t*) &dst_vec[basesize];
+
+ for(uint32_t j=0;j<extra;j++) {
+
+ edp[j]=esp[j];
+ }
+ }
}
}
@@ -5107,6 +5501,8 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
}
+ int16_t coeffp = CLAMP(coef*255,0,255);
+
for(int i=0;i<VS::ARRAY_MAX-1;i++) {
@@ -5116,9 +5512,13 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
int ofs = ad.ofs;
int src_stride=surf->stride;
- int dst_stride=surf->local_stride;
+ int dst_stride=skeleton_valid?surf->stride:surf->local_stride;
int count = surf->array_len;
+ if (!skeleton_valid && i>=VS::ARRAY_MAX-3)
+ break;
+
+
switch(i) {
case VS::ARRAY_VERTEX:
@@ -5134,7 +5534,21 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
dst[0]= src[0]*coef;
dst[1]= src[1]*coef;
dst[2]= src[2]*coef;
- } break;
+ };
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ for(int k=0;k<count;k++) {
+
+ const uint8_t *src = (const uint8_t*)&surf->array_local[ofs+k*src_stride];
+ uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride];
+
+ dst[0]= (src[0]*coeffp)>>8;
+ dst[1]= (src[1]*coeffp)>>8;
+ dst[2]= (src[2]*coeffp)>>8;
+ dst[3]= (src[3]*coeffp)>>8;
+ }
} break;
case VS::ARRAY_TEX_UV:
@@ -5147,16 +5561,32 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
dst[0]= src[0]*coef;
dst[1]= src[1]*coef;
- } break;
+ }
} break;
+ case VS::ARRAY_BONES:
+ case VS::ARRAY_WEIGHTS: {
+
+ 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];
+ dst[1]= src[1];
+ dst[2]= src[2];
+ dst[3]= src[3];
+ }
+
+ } break;
+
}
}
for(int j=0;j<surf->morph_target_count;j++) {
- for(int i=0;i<VS::ARRAY_MAX-1;i++) {
+ for(int i=0;i<VS::ARRAY_MAX-3;i++) {
const Surface::ArrayData& ad=surf->array[i];
if (ad.size==0)
@@ -5164,10 +5594,12 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
int ofs = ad.ofs;
- int dst_stride=surf->local_stride;
+ int src_stride=surf->local_stride;
+ int dst_stride=skeleton_valid?surf->stride:surf->local_stride;
int count = surf->array_len;
const uint8_t *morph=surf->morph_targets_local[j].array;
float w = p_morphs[j];
+ int16_t wfp = CLAMP(w*255,0,255);
switch(i) {
@@ -5178,13 +5610,26 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
for(int k=0;k<count;k++) {
- const float *src_morph = (const float*)&morph[ofs+k*dst_stride];
+ const float *src_morph = (const float*)&morph[ofs+k*src_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_COLOR: {
+ for(int k=0;k<count;k++) {
+
+ const uint8_t *src = (const uint8_t*)&morph[ofs+k*src_stride];
+ uint8_t *dst = (uint8_t*)&base[ofs+k*dst_stride];
+
+ dst[0]= (src[0]*wfp)>>8;
+ dst[1]= (src[1]*wfp)>>8;
+ dst[2]= (src[2]*wfp)>>8;
+ dst[3]= (src[3]*wfp)>>8;
+ }
} break;
case VS::ARRAY_TEX_UV:
@@ -5192,18 +5637,43 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
for(int k=0;k<count;k++) {
- const float *src_morph = (const float*)&morph[ofs+k*dst_stride];
+ const float *src_morph = (const float*)&morph[ofs+k*src_stride];
float *dst = (float*)&base[ofs+k*dst_stride];
dst[0]+= src_morph[0]*w;
dst[1]+= src_morph[1]*w;
- } break;
+ }
} break;
}
}
}
+
+
+ if (skeleton_valid) {
+
+
+
+ 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];
+ const Skeleton::Bone *skeleton = &p_skeleton->bones[0];
+
+
+ if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT)
+ _skeleton_xform<true,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
+ else if (surf->format&(VS::ARRAY_FORMAT_NORMAL))
+ _skeleton_xform<true,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
+ else if (surf->format&(VS::ARRAY_FORMAT_TANGENT))
+ _skeleton_xform<false,true,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
+ else
+ _skeleton_xform<false,false,true>(base,surf->stride,base,surf->stride,surf->array_len,src_bones,src_weights,skeleton);
+
+ }
+
+ stride=skeleton_valid?surf->stride:surf->local_stride;
+
+
#if 0
{
//in-place skeleton tansformation, only used for morphs, slow.
@@ -5297,14 +5767,14 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia
const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs];
const Skeleton::Bone *skeleton = &p_skeleton->bones[0];
- if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT)
- _skeleton_xform<true,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
+ if (surf->format&VS::ARRAY_FORMAT_NORMAL && surf->format&VS::ARRAY_FORMAT_TANGENT)
+ _skeleton_xform<true,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
else if (surf->format&(VS::ARRAY_FORMAT_NORMAL))
- _skeleton_xform<true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
+ _skeleton_xform<true,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
else if (surf->format&(VS::ARRAY_FORMAT_TANGENT))
- _skeleton_xform<false,true>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
+ _skeleton_xform<false,true,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
else
- _skeleton_xform<false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
+ _skeleton_xform<false,false,false>(surf->array_local,surf->stride,base,dst_stride,surf->array_len,src_bones,src_weights,skeleton);
stride=dst_stride;
@@ -5434,9 +5904,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) {
@@ -5737,7 +6208,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);
}
@@ -5786,7 +6257,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);
@@ -5805,6 +6276,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) {
@@ -5926,6 +6398,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) {
@@ -5936,9 +6424,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) {
@@ -5961,7 +6456,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
}
@@ -6037,7 +6532,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);
@@ -6046,11 +6549,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);
@@ -6059,13 +6567,13 @@ 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) {
if (!additive && current_env && current_env->fx_enabled[VS::ENV_FX_AMBIENT_LIGHT]) {
- Color ambcolor = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR];
+ Color ambcolor = _convert_color(current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_COLOR]);
float ambnrg = current_env->fx_param[VS::ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY];
material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHT,Vector3(ambcolor.r*ambnrg,ambcolor.g*ambnrg,ambcolor.b*ambnrg));
} else {
@@ -6793,6 +7301,7 @@ void RasterizerGLES2::end_scene() {
_debug_shadows();
}
// _debug_luminances();
+ _debug_samplers();
}
@@ -7193,6 +7702,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();
@@ -7255,10 +7796,11 @@ void RasterizerGLES2::canvas_begin() {
canvas_tex=RID();
//material_shader.unbind();
canvas_shader.unbind();
+ canvas_shader.set_custom_shader(0);
canvas_shader.bind();
canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0);
_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)
@@ -7272,6 +7814,9 @@ 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_shader=RID();
}
@@ -7354,7 +7899,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;
@@ -7362,14 +7907,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;
}
@@ -7378,6 +7925,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;
@@ -7720,8 +8270,18 @@ 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
+ //glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices );
} else {
glDrawArrays(GL_TRIANGLES,0,p_vertex_count);
}
@@ -7738,6 +8298,327 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) {
//canvas_transform = Variant(p_transform);
}
+
+void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
+
+
+ CanvasItem *current_clip=NULL;
+
+ canvas_opacity=1.0;
+ 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_shader=RID();
+ }
+
+ 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);
+ }
+ }
+
+
+ //begin rect
+ CanvasItem *shader_owner = ci->shader_owner?ci->shader_owner:ci;
+
+ if (shader_owner->shader!=canvas_last_shader) {
+
+ Shader *shader = NULL;
+ if (shader_owner->shader.is_valid()) {
+ shader = this->shader_owner.get(shader_owner->shader);
+ if (shader && !shader->valid) {
+ shader=NULL;
+ }
+ }
+
+ if (shader) {
+ canvas_shader.set_custom_shader(shader->custom_code_id);
+ if (canvas_shader.bind())
+ rebind_texpixel_size=true;
+
+ if (shader_owner->shader_version!=shader->version) {
+ //todo optimize uniforms
+ shader_owner->shader_version=shader->version;
+ }
+ //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=shader_owner->shader_param.find(E->key());
+ Variant &v=F?F->get():E->get().default_value;
+ if (v.get_type()==Variant::_RID || v.get_type()==Variant::OBJECT) {
+ int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic..
+
+ glActiveTexture(GL_TEXTURE0+tex_id);
+ RID tex = v;
+ Texture *t=texture_owner.get(tex);
+ if (!t)
+ glBindTexture(GL_TEXTURE_2D,white_tex);
+ else
+ glBindTexture(t->target,t->tex_id);
+
+ glUniform1i(loc,tex_id);
+ tex_id++;
+
+ } else {
+ canvas_shader.set_custom_uniform(idx,v);
+ }
+
+ idx++;
+ }
+
+
+ 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,tex_id);
+ glActiveTexture(GL_TEXTURE0+tex_id);
+ 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;
+ }
+ tex_id++;
+
+ }
+
+ if (tex_id>1) {
+ 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));
+ }
+
+ 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
+
+ uses_texpixel_size=shader->uses_texpixel_size;
+
+ } else {
+ canvas_shader.set_custom_shader(0);
+ canvas_shader.bind();
+ uses_texpixel_size=false;
+
+ }
+
+
+ canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
+ canvas_last_shader=shader_owner->shader;
+ }
+
+ 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);
+ 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_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;
+ }
+
+ int cc=ci->commands.size();
+ CanvasItem::Command **commands = ci->commands.ptr();
+
+ canvas_opacity = ci->final_opacity;
+
+ 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
+ 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);
+ canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color);
+
+ } break;
+ case CanvasItem::Command::TYPE_PRIMITIVE: {
+
+ 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: {
+
+ 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: {
+
+ 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;
+ }
+ }
+
+
+ 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() {
@@ -7810,6 +8691,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 {
@@ -8029,6 +8982,13 @@ 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 );
};
}
@@ -8617,6 +9577,16 @@ void RasterizerGLES2::init() {
use_texture_instancing=false;
use_attribute_instancing=true;
full_float_fb_supported=true;
+ srgb_supported=true;
+ latc_supported=true;
+ s3tc_srgb_supported=true;
+ use_anisotropic_filter=true;
+ float_linear_supported=true;
+ float_supported=true;
+ use_rgba_shadowmaps=false;
+
+ 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
use_rgba_shadowmaps=true;
use_fp16_fb=false;
@@ -8636,17 +9606,33 @@ void RasterizerGLES2::init() {
use_rgba_shadowmaps=true; //no other way, go back to rgba
}
pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc");
+ pvr_srgb_supported=extensions.has("GL_EXT_pvrtc_sRGB");
etc_supported=extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
use_depth24 = extensions.has("GL_OES_depth24");
s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
use_half_float = extensions.has("GL_OES_vertex_half_float");
atitc_supported=extensions.has("GL_AMD_compressed_ATC_texture");
+
+ srgb_supported=extensions.has("GL_EXT_sRGB");
+ s3tc_srgb_supported = s3tc_supported && extensions.has("GL_EXT_texture_compression_s3tc");
+ latc_supported = extensions.has("GL_EXT_texture_compression_latc");
+ anisotropic_level=1.0;
+ use_anisotropic_filter=extensions.has("GL_EXT_texture_filter_anisotropic");
+ if (use_anisotropic_filter) {
+ glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level);
+ anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0)));
+ }
+
+
print_line("S3TC: "+itos(s3tc_supported)+" ATITC: "+itos(atitc_supported));
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;
@@ -8684,7 +9670,7 @@ void RasterizerGLES2::init() {
-
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
//read_depth_supported=false;
{
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index a9fa7994e5..0f77d18dee 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -73,7 +73,10 @@ class RasterizerGLES2 : public Rasterizer {
uint8_t *skinned_buffer;
int skinned_buffer_size;
bool pvr_supported;
+ bool pvr_srgb_supported;
bool s3tc_supported;
+ bool s3tc_srgb_supported;
+ bool latc_supported;
bool etc_supported;
bool atitc_supported;
bool npo2_textures_available;
@@ -82,6 +85,10 @@ class RasterizerGLES2 : public Rasterizer {
bool full_float_fb_supported;
bool use_shadow_mapping;
bool use_fp16_fb;
+ bool srgb_supported;
+ bool float_supported;
+ bool float_linear_supported;
+
ShadowFilterTechnique shadow_filter;
bool use_shadow_esm;
@@ -91,13 +98,15 @@ class RasterizerGLES2 : public Rasterizer {
bool use_texture_instancing;
bool use_attribute_instancing;
bool use_rgba_shadowmaps;
+ bool use_anisotropic_filter;
+ float anisotropic_level;
bool use_half_float;
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;
@@ -110,6 +119,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;
@@ -181,10 +191,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;
@@ -203,6 +216,7 @@ class RasterizerGLES2 : public Rasterizer {
writes_vertex=false;
uses_discard=false;
uses_time=false;
+ uses_normal=false;
}
@@ -230,8 +244,9 @@ class RasterizerGLES2 : public Rasterizer {
struct UniformData {
+ bool inuse;
bool istexture;
- Variant value;
+ Variant value;
int index;
};
@@ -601,7 +616,7 @@ class RasterizerGLES2 : public Rasterizer {
mutable SelfList<Skeleton>::List _skeleton_dirty_list;
- template<bool USE_NORMAL, bool USE_TANGENT>
+ template<bool USE_NORMAL, bool USE_TANGENT,bool INPLACE>
void _skeleton_xform(const uint8_t * p_src_array, int p_src_stride, uint8_t * p_dst_array, int p_dst_stride, int p_elements,const uint8_t *p_src_bones, const uint8_t *p_src_weights, const Skeleton::Bone *p_bone_xforms);
struct Light {
@@ -697,6 +712,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
@@ -794,6 +821,7 @@ class RasterizerGLES2 : public Rasterizer {
RID shadow_material;
Material *shadow_mat_ptr;
+ int max_texture_units;
GLuint base_framebuffer;
GLuint gui_quad_buffer;
@@ -1064,6 +1092,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();
+
/***********/
@@ -1142,6 +1172,13 @@ class RasterizerGLES2 : public Rasterizer {
GLuint white_tex;
RID canvas_tex;
float canvas_opacity;
+ bool uses_texpixel_size;
+ bool rebind_texpixel_size;
+ Transform canvas_transform;
+ RID canvas_last_shader;
+ bool canvas_texscreen_used;
+
+
_FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture);
VS::MaterialBlendMode canvas_blend_mode;
@@ -1172,7 +1209,7 @@ class RasterizerGLES2 : public Rasterizer {
RID overdraw_material;
mutable MaterialShaderGLES2 material_shader;
- CanvasShaderGLES2 canvas_shader;
+ mutable CanvasShaderGLES2 canvas_shader;
BlurShaderGLES2 blur_shader;
CopyShaderGLES2 copy_shader;
@@ -1230,6 +1267,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 */
@@ -1507,6 +1548,8 @@ 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);
+
/* ENVIRONMENT */
@@ -1524,6 +1567,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*/
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index ada9efa4b3..f1ddcf8009 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -131,6 +131,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 +142,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,11 +174,17 @@ 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) {
uses_discard=true;
}
+ if (vnode->name==vname_normalmap) {
+ uses_normalmap=true;
+ }
if (vnode->name==vname_screen_uv) {
uses_screen_uv=true;
}
@@ -209,6 +218,47 @@ 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 (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_time) {
uses_time=true;
@@ -354,7 +404,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") {
@@ -546,6 +596,9 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
uses_screen_uv=false;
uses_light=false;
uses_time=false;
+ uses_normalmap=false;
+ uses_normal=false;
+ uses_texpixel_size=false;
vertex_code_writes_vertex=false;
uniforms=r_uniforms;
flags=&r_flags;
@@ -555,6 +608,8 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
r_flags.use_tangent_interp=false;
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;
@@ -576,8 +631,12 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
r_flags.uses_screen_uv=uses_screen_uv;
r_flags.uses_light=uses_light;
r_flags.uses_time=uses_time;
+ r_flags.uses_normalmap=uses_normalmap;
+ r_flags.uses_normal=uses_normalmap;
+ r_flags.uses_texpixel_size=uses_texpixel_size;
r_code_line=code;
r_globals_line=global_code;
+
return OK;
}
@@ -631,6 +690,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";
@@ -669,7 +729,10 @@ 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";
mode_replace_table[1]["VAR1"]="var1_interp";
mode_replace_table[1]["VAR2"]="var2_interp";
mode_replace_table[1]["UV"]="uv";
@@ -709,6 +772,42 @@ 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]["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]["SRC_COLOR"]="color";
+ mode_replace_table[5]["COLOR"]="color";
+ mode_replace_table[5]["NORMAL"]="normal";
+ mode_replace_table[5]["LIGHT_DIR"]="light_dir";
+ mode_replace_table[5]["LIGHT_DISTANCE"]="light_distance";
+ mode_replace_table[5]["LIGHT"]="light";
+ 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";
@@ -728,5 +827,8 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
vname_vertex="VERTEX";
vname_light="LIGHT";
vname_time="TIME";
+ vname_normalmap="NORMALMAP";
+ vname_normal="NORMAL";
+ vname_texpixel_size="TEXTURE_PIXEL_SIZE";
}
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 3dfdd81c0d..a10fa6dfe0 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -50,6 +50,9 @@ private:
bool uses_discard;
bool uses_time;
bool uses_screen_uv;
+ bool uses_normalmap;
+ bool uses_normal;
+ bool uses_texpixel_size;
bool vertex_code_writes_vertex;
Flags *flags;
@@ -66,6 +69,9 @@ private:
StringName vname_vertex;
StringName vname_light;
StringName vname_time;
+ StringName vname_normalmap;
+ StringName vname_normal;
+ StringName vname_texpixel_size;
Map<StringName,ShaderLanguage::Uniform> *uniforms;
@@ -77,7 +83,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:
@@ -87,6 +93,7 @@ public:
bool uses_alpha;
bool uses_texscreen;
bool uses_texpos;
+ bool uses_normalmap;
bool vertex_code_writes_vertex;
bool uses_discard;
bool uses_screen_uv;
@@ -98,6 +105,8 @@ public:
bool use_var2_interp;
bool uses_light;
bool uses_time;
+ bool uses_normal;
+ bool uses_texpixel_size;
};
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/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index f36741d586..464cb9e188 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -18,19 +18,56 @@ 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;
+varying vec4 light_tex_pos;
+
+#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);
+{
+ vec2 src_vtx=outvec.xy;
+VERTEX_SHADER_CODE
+
+}
outvec = extra_matrix * outvec;
outvec = modelview_matrix * outvec;
#ifdef USE_PIXEL_SNAP
- outvec.xy=floor(outvec.xy+0.5);
+ outvec.xy=floor(outvec.xy+0.5);
#endif
+
+
+#ifdef USE_LIGHTING
+
+ light_tex_pos.xy = light_matrix * outvec;
+ light_tex_pos.zw=outvec.xy - light_matrix[4].xy; //likely wrong
+
+#endif
+
+
gl_Position = projection_matrix * outvec;
}
@@ -54,17 +91,112 @@ 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_LIGHTING
+
+uniform sampler2D light_texture;
+varying vec4 light_tex_pos;
+
+#ifdef USE_SHADOWS
+
+uniform sampler2D shadow_texture;
+uniform float shadow_attenuation;
+
+#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,1);
+#endif
+
color *= texture2D( texture, uv_interp );
+#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_LIGHTING
+
+ float att=1.0;
+
+ vec3 light = texture2D(light_texture,light_tex_pos).rgb;
+#ifdef USE_SHADOWS
+ //this might not be that great on mobile?
+ float light_dist = length(light_texture.zw);
+ float light_angle = atan2(light_texture.x,light_texture.z) + 1.0 * 0.5;
+ float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0));
+ if (light_dist>shadow_dist) {
+ light*=shadow_attenuation;
+ }
+//use shadows
+#endif
+
+#if defined(USE_LIGHT_SHADER_CODE)
+//light is written by the light shader
+{
+ vec2 light_dir = normalize(light_tex_pos.zw);
+ float light_distance = length(light_tex_pos.zw);
+LIGHT_SHADER_CODE
+}
+#else
+
+#if defined(NORMAL_USED)
+ vec2 light_normal = normalize(light_tex_pos.zw);
+ light = color.rgb * light * max(dot(light_normal,normal),0);
+#endif
+
+ color.rgb=light;
+//light shader code
+#endif
+
+//use lighting
+#endif
// color.rgb*=color.a;
gl_FragColor = color;
diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl
index d8fb03f3a3..ae7185a1d6 100644
--- a/drivers/gles2/shaders/copy.glsl
+++ b/drivers/gles2/shaders/copy.glsl
@@ -46,6 +46,15 @@ precision mediump int;
#endif
+
+float sRGB_gamma_correct(float c){
+ float a = 0.055;
+ if(c < 0.0031308)
+ return 12.92*c;
+ else
+ return (1.0+a)*pow(c, 1.0/2.4) - a;
+}
+
#define LUM_RANGE 4.0
@@ -407,15 +416,26 @@ void main() {
#ifdef USE_SRGB
+#if 0
+ //this was fast, but was commented out because it looked kind of shitty, might it be fixable?
+
{ //i have my doubts about how fast this is
+
color.rgb = min(color.rgb,vec3(1.0)); //clamp just in case
vec3 S1 = sqrt(color.rgb);
vec3 S2 = sqrt(S1);
vec3 S3 = sqrt(S2);
color.rgb = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.225411470 * color.rgb;
}
+#else
+
+ color.r=sRGB_gamma_correct(color.r);
+ color.g=sRGB_gamma_correct(color.g);
+ color.b=sRGB_gamma_correct(color.b);
+
#endif
+#endif
#ifdef USE_HDR_COPY
diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl
index ad8a364ac1..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
@@ -292,11 +292,21 @@ void main() {
normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz);
#if defined(ENABLE_COLOR_INTERP)
+#ifdef USE_COLOR_ATTRIB_SRGB_TO_LINEAR
+
+ color_interp = vec4(
+ color_attrib.r<0.04045 ? color_attrib.r * (1.0 / 12.92) : pow((color_attrib.r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+ color_attrib.g<0.04045 ? color_attrib.g * (1.0 / 12.92) : pow((color_attrib.g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+ color_attrib.b<0.04045 ? color_attrib.b * (1.0 / 12.92) : pow((color_attrib.b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+ color_attrib.a
+ );
+#else
color_interp = color_attrib;
#endif
+#endif
#if defined(ENABLE_TANGENT_INTERP)
- tangent_interp=normalize(tangent_in);
+ tangent_interp=normalize((modelview * vec4(tangent_in,0.0)).xyz);
binormal_interp = normalize( cross(normal_interp,tangent_interp) * binormalf );
#endif
@@ -585,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;
@@ -599,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
@@ -761,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
@@ -809,6 +828,12 @@ void main() {
vec4 color = color_interp;
#endif
+#if defined(ENABLE_NORMALMAP)
+
+ vec3 normalmap = vec3(0.0);
+#endif
+
+ float normaldepth=1.0;
@@ -823,6 +848,12 @@ FRAGMENT_SHADER_CODE
}
+#if defined(ENABLE_NORMALMAP)
+
+ normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side;
+
+#endif
+
#if defined(ENABLE_DISCARD)
if (discard_) {
//easy to eliminate dead code
@@ -896,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;
@@ -912,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
@@ -1164,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
@@ -1180,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
@@ -1202,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/core/io/object_saver_base.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index d9ec4a3aba..e82e0c24be 100644
--- a/core/io/object_saver_base.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* object_saver_base.h */
+/* audio_driver_pulseaudio.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -26,51 +26,54 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OBJECT_SAVER_BASE_H
-#define OBJECT_SAVER_BASE_H
+#include "servers/audio/audio_server_sw.h"
+#ifdef PULSEAUDIO_ENABLED
-#ifdef OLD_SCENE_FORMAT_ENABLED
-#include "object_saver.h"
+#include "core/os/thread.h"
+#include "core/os/mutex.h"
-#include "map.h"
-#include "resource.h"
+#include <pulse/simple.h>
-class ObjectSaverBase : public ObjectFormatSaver {
+class AudioDriverPulseAudio : public AudioDriverSW {
-protected:
+ Thread* thread;
+ Mutex* mutex;
- Map<RES,int> resource_map;
+ pa_simple* pulse;
- struct SavedObject {
+ int32_t* samples_in;
+ int16_t* samples_out;
- Variant meta;
- String type;
+ static void thread_func(void* p_udata);
+ unsigned int mix_rate;
+ OutputFormat output_format;
- struct SavedProperty {
+ unsigned int buffer_size;
+ int channels;
- String name;
- Variant value;
- };
+ bool active;
+ bool thread_exited;
+ mutable bool exit_thread;
+ bool pcm_open;
- List<SavedProperty> properties;
- };
-
- List<RES> saved_resources;
-
- List<SavedObject*> saved_objects;
-
- void _find_resources(const Variant& p_variant);
-
- virtual Error write()=0;
public:
- virtual Error save(const Object *p_object,const Variant &p_meta);
+ 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();
- ObjectSaverBase();
- ~ObjectSaverBase();
+ AudioDriverPulseAudio();
+ ~AudioDriverPulseAudio();
};
#endif
-#endif // OBJECT_SAVER_BASE_H
diff --git a/drivers/squish/image_compress_squish.cpp b/drivers/squish/image_compress_squish.cpp
index 1d71f51db4..2c520bd1e9 100644
--- a/drivers/squish/image_compress_squish.cpp
+++ b/drivers/squish/image_compress_squish.cpp
@@ -18,18 +18,19 @@ void image_compress_squish(Image *p_image) {
if (p_image->get_format()>=Image::FORMAT_BC1)
return; //do not compress, already compressed
-
- Image::AlphaMode alpha = p_image->detect_alpha();
- Image::Format target_format;
int shift=0;
int squish_comp=squish::kColourRangeFit;
- switch(alpha) {
+ Image::Format target_format;
- case Image::ALPHA_NONE: target_format = Image::FORMAT_BC1; shift=1; squish_comp|=squish::kDxt1; break;
- case Image::ALPHA_BIT: target_format = Image::FORMAT_BC2; squish_comp|=squish::kDxt3; break;
- case Image::ALPHA_BLEND: target_format = Image::FORMAT_BC3; squish_comp|=squish::kDxt5; break;
- }
+ if (p_image->get_format()==Image::FORMAT_GRAYSCALE_ALPHA) {
+ //compressed normalmap
+ target_format = Image::FORMAT_BC3; squish_comp|=squish::kDxt5;;
+ } else if (p_image->detect_alpha()!=Image::ALPHA_NONE) {
+ target_format = Image::FORMAT_BC2; squish_comp|=squish::kDxt3;;
+ } else {
+ target_format = Image::FORMAT_BC1; shift=1; squish_comp|=squish::kDxt1;;
+ }
p_image->convert(Image::FORMAT_RGBA); //always expects rgba
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 12ef5de88f..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 {
@@ -86,12 +91,18 @@ public:
return fa->get_pos();
};
- TPDataFA(String p_path) {
+ TPDataFA(const String& p_path) {
fa = FileAccess::open(p_path, FileAccess::READ);
data_name = "File: " + p_path;
};
+ TPDataFA(FileAccess* p_fa, const String& p_path) {
+
+ fa = p_fa;
+ data_name = "File: " + p_path;
+ };
+
~TPDataFA() {
if (fa)
@@ -101,6 +112,8 @@ public:
class AudioStreamInput : public AudioStreamResampled {
+ _THREAD_SAFE_CLASS_;
+
int channels;
int freq;
@@ -108,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() {};
+ virtual void stop() {
+
+ _THREAD_SAFE_METHOD_
+
+ AudioServer::get_singleton()->stream_set_active(stream_rid,false);
+ //_clear_stream();
+ playing=false;
+ _clear();
+ };
+
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; };
@@ -135,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;
};
@@ -175,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 {
@@ -200,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)));
@@ -209,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);
}
};
@@ -226,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;
};
};
@@ -236,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 {
@@ -252,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 {
@@ -300,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;
@@ -323,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) {
@@ -348,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) {
@@ -364,26 +452,44 @@ 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);
+ if (!f || !f->is_open())
+ return;
+
if (!audio_factory) {
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 {
- TheoraDataSource* ds = memnew(TPDataFA(p_file));
+ TheoraDataSource* ds = memnew(TPDataFA(f, 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;
@@ -396,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/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index c221743457..841160f941 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
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..2de975e5d1 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -42,6 +42,7 @@
#include "dir_access_unix.h"
#include "tcp_server_posix.h"
#include "stream_peer_tcp_posix.h"
+#include "packet_peer_udp_posix.h"
#include <stdarg.h>
@@ -115,6 +116,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;
@@ -330,6 +332,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;
}
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/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 aefec59ce0..d1e9766105 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -106,6 +106,7 @@ String DirAccessWindows::get_next() {
return name;
} else {
+#ifndef WINRT_ENABLED
_cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
String name=p->f.cFileName;
@@ -117,7 +118,8 @@ String DirAccessWindows::get_next() {
}
return name;
-
+#endif
+ return "";
}
}
@@ -189,10 +191,10 @@ Error DirAccessWindows::change_dir(String p_dir) {
current_dir=real_current_dir_name; // TODO, utf8 parser
current_dir=current_dir.replace("\\","/");
- } else {
+ } //else {
SetCurrentDirectoryW(prev_dir.c_str());
- }
+ //}
return worked?OK:ERR_INVALID_PARAMETER;
} else {
@@ -210,10 +212,10 @@ Error DirAccessWindows::change_dir(String p_dir) {
current_dir=real_current_dir_name; // TODO, utf8 parser
current_dir=current_dir.replace("\\","/");
- } else {
+ }// else {
SetCurrentDirectoryA(prev_dir.ascii().get_data());
- }
+ //}
return worked?OK:ERR_INVALID_PARAMETER;
@@ -352,22 +354,23 @@ bool DirAccessWindows::dir_exists(String p_dir) {
DWORD fileAttr;
fileAttr = GetFileAttributesExW(p_dir.c_str(), GetFileExInfoStandard, &fileInfo);
- if (0xFFFFFFFF == fileAttr)
+ if (0 == fileAttr)
return false;
return (fileAttr&FILE_ATTRIBUTE_DIRECTORY);
} else {
+#ifndef WINRT_ENABLED
DWORD fileAttr;
fileAttr = GetFileAttributesExA(p_dir.ascii().get_data(), GetFileExInfoStandard, &fileInfo);
- if (0xFFFFFFFF == fileAttr)
+ if (0 == fileAttr)
return false;
return (fileAttr&FILE_ATTRIBUTE_DIRECTORY);
+#endif
}
-
return false;
}
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 3cd065841f..a6073cbb29 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -54,7 +54,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();
diff --git a/main/SCsub b/main/SCsub
index 7b51b06187..795c427c8d 100644
--- a/main/SCsub
+++ b/main/SCsub
@@ -5,7 +5,7 @@ env.add_source_files(env.main_sources,"*.cpp")
Export('env')
-lib = env.Library("main",env.main_sources, LIBSUFFIX=env['platform_libsuffix'])
+lib = env.Library("main",env.main_sources)
env.Prepend(LIBS=[lib])
diff --git a/main/main.cpp b/main/main.cpp
index 2d286759d9..f0e376a045 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -43,7 +43,7 @@
#include "io/resource_loader.h"
#include "scene/main/scene_main_loop.h"
-#include "scene/io/scene_loader.h"
+
#include "script_language.h"
#include "io/resource_loader.h"
@@ -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);
@@ -1131,10 +1134,6 @@ bool Main::start() {
#ifdef TOOLS_ENABLED
if (editor) {
-#ifdef OLD_SCENE_FORMAT_ENABLED
- if (convert_old)
- editor_node->set_convert_old_scene(true);
-#endif
if (_import!="") {
@@ -1214,14 +1213,6 @@ bool Main::start() {
if (scenedata.is_valid())
scene=scenedata->instance();
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
- if (!scene) {
- scene = SceneLoader::load(local_game_path,true);
- }
-
-#endif
-
ERR_EXPLAIN("Failed loading scene: "+local_game_path);
ERR_FAIL_COND_V(!scene,false)
sml->get_root()->add_child(scene);
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 58cc41f70a..0c0c5a05e3 100755
--- a/methods.py
+++ b/methods.py
@@ -205,7 +205,7 @@ def build_glsl_header( filename ):
out_file_base = out_file
out_file_base = out_file_base[ out_file_base.rfind("/")+1: ]
out_file_base = out_file_base[ out_file_base.rfind("\\")+1: ]
- print("out file "+out_file+" base " +out_file_base)
+# print("out file "+out_file+" base " +out_file_base)
out_file_ifdef = out_file_base.replace(".","_").upper()
fd.write("#ifndef "+out_file_ifdef+"\n")
fd.write("#define "+out_file_ifdef+"\n")
@@ -504,7 +504,7 @@ def build_hlsl_dx9_header( filename ):
out_file_base = out_file
out_file_base = out_file_base[ out_file_base.rfind("/")+1: ]
out_file_base = out_file_base[ out_file_base.rfind("\\")+1: ]
- print("out file "+out_file+" base " +out_file_base)
+# print("out file "+out_file+" base " +out_file_base)
out_file_ifdef = out_file_base.replace(".","_").upper()
fd.write("#ifndef "+out_file_ifdef+"\n")
fd.write("#define "+out_file_ifdef+"\n")
@@ -714,7 +714,7 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ):
enumbase = ifdefline[:ifdefline.find("_EN_")];
ifdefline = ifdefline.replace("_EN_","_")
line = line.replace("_EN_","_")
- print(enumbase+":"+ifdefline);
+# print(enumbase+":"+ifdefline);
if (enumbase not in enums):
enums[enumbase]=[]
if (ifdefline not in enums[enumbase]):
@@ -805,7 +805,7 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ):
out_file_base = out_file
out_file_base = out_file_base[ out_file_base.rfind("/")+1: ]
out_file_base = out_file_base[ out_file_base.rfind("\\")+1: ]
- print("out file "+out_file+" base " +out_file_base)
+# print("out file "+out_file+" base " +out_file_base)
out_file_ifdef = out_file_base.replace(".","_").upper()
fd.write("#ifndef "+out_file_ifdef+class_suffix+"_120\n")
fd.write("#define "+out_file_ifdef+class_suffix+"_120\n")
@@ -952,10 +952,10 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ):
x=enums[xv]
bits=1
amt = len(x);
- print(x)
+# print(x)
while(2**bits < amt):
bits+=1
- print("amount: "+str(amt)+" bits "+str(bits));
+# print("amount: "+str(amt)+" bits "+str(bits));
strs="{"
for i in range(amt):
strs+="\"#define "+x[i]+"\\n\","
@@ -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")
@@ -1330,7 +1299,7 @@ def save_active_platforms(apnames,ap):
for x in ap:
pth = x+"/logo.png"
- print("open path: "+pth)
+# print("open path: "+pth)
pngf=open(pth,"rb");
b=pngf.read(1);
str=" /* AUTOGENERATED FILE, DO NOT EDIT */ \n"
diff --git a/modules/SCsub b/modules/SCsub
index 9b42a14e31..d215f72c08 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -16,7 +16,7 @@ for x in env.module_list:
env_modules.Append(CPPFLAGS=["-DMODULE_"+x.upper()+"_ENABLED"])
SConscript(x+"/SCsub")
-lib = env_modules.Library("modules",env.modules_sources, LIBSUFFIX=env['platform_libsuffix'])
+lib = env_modules.Library("modules",env.modules_sources)
env.Prepend(LIBS=[lib])
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..b83d0ded4b 100644
--- a/modules/gdscript/gd_compiler.h
+++ b/modules/gdscript/gd_compiler.h
@@ -153,11 +153,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 a98b07ab92..20cd09efd0 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 {
@@ -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();
@@ -114,6 +115,7 @@ int GDScriptLanguage::find_function(const String& p_function,const String& p_cod
if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) {
indent=tokenizer.get_token_line_indent();
}
+ //print_line("TOKEN: "+String(GDTokenizer::get_token_name(tokenizer.get_token())));
if (indent==0 && tokenizer.get_token()==GDTokenizer::TK_PR_FUNCTION && tokenizer.get_token(1)==GDTokenizer::TK_IDENTIFIER) {
String identifier = tokenizer.get_token_identifier(1);
@@ -122,6 +124,8 @@ int GDScriptLanguage::find_function(const String& p_function,const String& p_cod
}
}
tokenizer.advance();
+ //print_line("NEXT: "+String(GDTokenizer::get_token_name(tokenizer.get_token())));
+
}
return -1;
}
@@ -247,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));
}
}
@@ -308,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++) {
+
+ String subclass=context._class->extends_class[i];
- GDNativeClass *gnc = o->cast_to<GDNativeClass>();
- _parse_native_symbols(gnc->get_name(),false,r_options);
+ 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()) {
+
+ int argindex = -1;
- //parse indices in expressions :|
- for (int i=0;i<p_block->statements.size();i++) {
+ for(int i=0;i<context.function->arguments.size();i++) {
- if (p_block->statements[i]->line>p_line)
+ if (context.function->arguments[i]==p_identifier) {
+ argindex=i;
break;
+ }
+
+ }
- if (p_block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) {
+ if (argindex!=-1) {
+ GDCompletionIdentifier id =_get_native_class(context);
+ if (id.type==Variant::OBJECT && id.obj_type!=StringName()) {
+ //this kinda sucks but meh
- const GDParser::LocalVarNode *lv=static_cast<const GDParser::LocalVarNode *>(p_block->statements[i]);
- if (lv->assign && String(lv->name)==p_indices->get()) {
+ List<MethodInfo> vmethods;
+ ObjectTypeDB::get_virtual_methods(id.obj_type,&vmethods);
+ for (List<MethodInfo>::Element *E=vmethods.front();E;E=E->next()) {
- _parse_expression_node(lv->assign,r_options,p_indices->next());
- return true;
+
+ 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;
+ }
+ }
}
}
}
+ }
- } 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;
+ //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;
+ }
+ }
+ 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) {
- //for (Map<StringName,Ref<GDScript> >::Element ?
+ if (p_only_functions)
+ return;
+
+ for (int i=0;i<context.block->statements.size();i++) {
+
+ if (context.block->statements[i]->line>p_line)
+ continue;
- if (!p_static && !p_indices) {
- for(const Set<StringName>::Element *E=p_script->get_members().front();E;E=E->next()) {
- r_options->push_back(E->get());
+ if (context.block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) {
+
+ 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..fcfbbb04da 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -1166,6 +1166,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 +1175,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;
@@ -1231,6 +1234,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: {
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 49d92e0746..0aa115ffbc 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -820,7 +820,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 +1440,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 +1523,7 @@ void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
placeholders.erase(p_placeholder);
}
+/*
void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {
@@ -1537,7 +1538,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 +1564,7 @@ void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {
p_placeholder->update(plist,default_values);
-}
+}*/
#endif
ScriptInstance* GDScript::instance_create(Object *p_this) {
@@ -1582,7 +1583,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,46 +1625,157 @@ 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
+
}
-void GDScript::update_exports() {
+#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();
+ }
+
+ 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;
- if (basedir=="")
- basedir=get_path();
+ bool changed=false;
- if (basedir!="")
- basedir=basedir.get_base_dir();
+ if (source_changed_cache) {
+ //print_line("updating source for "+get_path());
+ source_changed_cache=false;
+ changed=true;
- GDParser parser;
- Error err = parser.parse(source,basedir,true);
- if (err)
- return; //do none
+ String basedir=path;
- const GDParser::Node* root = parser.get_parse_tree();
- ERR_FAIL_COND(root->type!=GDParser::Node::TYPE_CLASS);
+ if (basedir=="")
+ basedir=get_path();
- const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode*>(root);
+ if (basedir!="")
+ basedir=basedir.get_base_dir();
- List<PropertyInfo> plist;
+ GDParser parser;
+ Error err = parser.parse(source,basedir,true,path);
- Map<StringName,Variant> default_values;
+ if (err==OK) {
- for(int i=0;i<c->variables.size();i++) {
- if (c->variables[i]._export.type==Variant::NIL)
- continue;
+ const GDParser::Node* root = parser.get_parse_tree();
+ ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,false);
+
+ const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode*>(root);
+
+ if (base_cache.is_valid()) {
+ base_cache->inheriters_cache.erase(get_instance_ID());
+ base_cache=Ref<GDScript>();
+ }
+
+
+ if (c->extends_used && String(c->extends_file)!="") {
+
+ String path = c->extends_file;
+ if (path.is_rel_path()) {
+
+ String base = get_path();
+ if (base=="" || base.is_rel_path()) {
+
+ 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=placeholders.front();E;E=E->next()) {
+
+ E->get()->update(propnames,values);
+ }
+ }
+
+ return changed;
+
+#endif
+ return false;
+}
- for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
+void GDScript::update_exports() {
+
+#ifdef TOOLS_ENABLED
- E->get()->update(plist,default_values);
+ _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
@@ -1695,7 +1808,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());
@@ -1723,10 +1836,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;
}
@@ -1869,7 +1982,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);
@@ -1922,6 +2035,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;
@@ -1938,9 +2055,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();
}
@@ -1963,6 +2080,9 @@ GDScript::GDScript() {
_base=NULL;
_owner=NULL;
tool=false;
+#ifdef TOOLS_ENABLED
+ source_changed_cache=false;
+#endif
}
@@ -1979,11 +2099,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;
-
}
}
@@ -2016,9 +2143,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
}
@@ -2108,7 +2242,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);
@@ -2410,8 +2544,8 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"func" ,
"if" ,
"in" ,
- "varl",
"null" ,
+ "not" ,
"return" ,
"self" ,
"while" ,
@@ -2419,6 +2553,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"false" ,
"tool",
"var",
+ "setget",
"pass",
"and",
"or",
@@ -2426,6 +2561,8 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"assert",
"yield",
"static",
+ "float",
+ "int",
0};
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 2088606271..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,11 +291,14 @@ 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
+
+ bool _update_exports();
+
protected:
bool _get(const StringName& p_name,Variant &r_ret) const;
bool _set(const StringName& p_name, const Variant& p_value);
@@ -274,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; }
@@ -285,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;
@@ -469,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..6f968f2080 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,43 @@ 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 '\'':
+ string_mode=STRING_SINGLE_QUOTE;
case '"': {
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( string_mode==STRING_SINGLE_QUOTE && CharType(GETCHAR(i))=='\'' ) {
break;
- } else if (CharType(GETCHAR(i)=='\\')) {
+ } 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 +649,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 +848,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 +1033,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..7c344e1e90 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -677,7 +677,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 +1041,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/SCsub b/platform/android/SCsub
index 699db30cad..cffec5ae95 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -66,6 +66,6 @@ for x in env.android_module_libraries:
shutil.copy(x,abspath+"/java/libs")
-env_android.SharedLibrary("#platform/android/libgodot_android.so",[android_objects])
+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'))
+#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/detect.py b/platform/android/detect.py
index 0c860c23b1..4cf12538db 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -27,14 +27,13 @@ def get_opts():
('NDK_TARGET', 'toolchain to use for the NDK',"arm-linux-androideabi-4.8"),
('android_stl','enable STL support in android port (for modules)','no'),
('armv6','compile for older phones running arm v6 (instead of v7+neon+smp)','no'),
- ('x86','compile for x86','no')
+ ('x86','Xompile for Android-x86','no')
]
def get_flags():
return [
- ('lua', 'no'),
('tools', 'no'),
('nedmalloc', 'no'),
('builtin_zlib', 'no'),
@@ -62,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")
@@ -77,13 +77,7 @@ def configure(env):
env.Append(CPPPATH=['#platform/android'])
if env['x86']=='yes':
- env['OBJSUFFIX'] = ".android.ox"
- env['LIBSUFFIX'] = ".android.ax"
- else:
- env['OBJSUFFIX'] = ".android.o"
- env['LIBSUFFIX'] = ".android.a"
- env['PROGSUFFIX'] = ".android"
- env['SHLIBSUFFIX'] = ".so"
+ env.extra_suffix=".x86"
gcc_path=env["ANDROID_NDK_ROOT"]+"/toolchains/"+env["NDK_TARGET"]+"/prebuilt/";
@@ -128,13 +122,13 @@ def configure(env):
ld_path=env["ANDROID_NDK_ROOT"]+"/platforms/"+ndk_platform+"/"+env['ARCH']+"/usr/lib"
env.Append(CPPPATH=[gcc_include])
# env['CCFLAGS'] = string.split('-DNO_THREADS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -mthumb -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED ')
- print("********* armv6", env['armv6'])
+
if env['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'])
@@ -149,23 +143,10 @@ def configure(env):
if (env["target"]=="release"):
env.Append(CCFLAGS=['-O2', '-ffast-math','-fomit-frame-pointer'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="release_debug"):
env.Append(CCFLAGS=['-O2', '-ffast-math','-DDEBUG_ENABLED'])
- env['OBJSUFFIX'] = "_optd"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_optd"+env['LIBSUFFIX']
-
- elif (env["target"]=="profile"):
-
- env.Append(CCFLAGS=['-O2', '-ffast-math','-fomit-frame-pointer', '-g1'])
- env.Append(LIBPATH=['#platform/android/armeabi'])
- env.Append(LIBS=['andprof'])
- env['OBJSUFFIX'] = "_prof"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_prof"+env['LIBSUFFIX']
- env['SHLIBSUFFIX'] = "_prof"+env['SHLIBSUFFIX']
elif (env["target"]=="debug"):
@@ -174,8 +155,10 @@ def configure(env):
if env["armv6"] == "no" and env['x86'] != 'yes':
env['neon_enabled']=True
+
env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL','-DMPC_FIXED_POINT'])
# env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED','-DMPC_FIXED_POINT'])
+
if (env['android_stl']=='yes'):
#env.Append(CCFLAGS=[env["ANDROID_NDK_ROOT"]+"/sources/cxx-stl/system/include"])
env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"]+"/sources/cxx-stl/gnu-libstdc++/4.4.3/include"])
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index aef223470a..3e4ea8a4e0 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -184,6 +184,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
String cmdline;
bool _signed;
bool apk_expansion;
+ bool remove_prev;
String apk_expansion_salt;
String apk_expansion_pkey;
int orientation;
@@ -258,7 +259,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;
@@ -321,7 +324,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;
@@ -378,6 +383,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"));
@@ -392,8 +398,9 @@ void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list
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 ) );
@@ -1222,7 +1229,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 +1238,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 +1460,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 +1481,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 +1491,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 +1533,7 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
device_lock = Mutex::create();
quit_request=false;
orientation=0;
+ remove_prev=true;
device_thread=Thread::create(_device_poll_thread,this);
devices_changed=true;
@@ -1613,6 +1632,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..1a7659a473 100644
--- a/platform/android/java/src/com/android/godot/Godot.java
+++ b/platform/android/java/src/com/android/godot/Godot.java
@@ -358,7 +358,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;
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_glue.cpp b/platform/android/java_glue.cpp
index fdc6f1207d..0312d13644 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -205,6 +205,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 ));
@@ -599,7 +600,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 +660,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 +747,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 +790,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 +822,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");
diff --git a/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
index da9d06e63c..77ebb4b780 100644
--- a/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
+++ b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
@@ -2,5 +2,5 @@
package com.android.vending.expansion.downloader;
public final class BuildConfig {
- public final static boolean DEBUG = false;
+ public final static boolean DEBUG = true;
} \ No newline at end of file
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 5fad4386fa..6f1c03b593 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) );
}
@@ -699,12 +699,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 +733,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..26dbf4a509 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;
@@ -203,6 +206,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 +215,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/flash/SCsub b/platform/flash/SCsub
index 0dea7bf011..b7aef3b65d 100644
--- a/platform/flash/SCsub
+++ b/platform/flash/SCsub
@@ -8,7 +8,6 @@ common_flash=[\
#"dir_access_flash.cpp",
]
-print("** path is ", env['ENV']['PATH'])
abc = env.Command('#platform/flash/Console.abc', '#platform/flash/Console.as',
"""
diff --git a/platform/flash/detect.py b/platform/flash/detect.py
index 56d2516ab5..5507ce5177 100644
--- a/platform/flash/detect.py
+++ b/platform/flash/detect.py
@@ -11,7 +11,6 @@ def get_name():
def can_build():
#import os
- print(os.environ)
if (not os.environ.has_key("FLASCC_ROOT")):
return False
return True
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index d30d101e1b..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'])
@@ -35,11 +33,6 @@ if env['ios_appirater'] == "yes":
obj = env_ios.Object('godot_iphone.cpp')
prog = None
-if env["target"]=="release" or env["target"] == "release_debug":
- 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 bin/godot.iphone.dSYM"
- env.AddPostAction(prog, action)
+prog = env_ios.Program('#bin/godot', [obj] + iphone_lib)
+action = "dsymutil "+File(prog)[0].path+" -o " + File(prog)[0].path + ".dSYM"
+env.AddPostAction(prog, action)
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 9877e09ade..6ca54286ba 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**);
@@ -127,7 +129,7 @@ static int frame_count = 0;
OSIPhone::get_singleton()->set_unique_ID(String::utf8([uuid UTF8String]));
- }; // break;
+ }; break;
/*
case 1: {
++frame_count;
@@ -154,7 +156,7 @@ static int frame_count = 0;
[Appirater appLaunched:YES app_id:aid];
#endif
- }; // break; fallthrough
+ }; break; // no fallthrough
default: {
@@ -257,8 +259,12 @@ static int frame_count = 0;
- (void)applicationDidEnterBackground:(UIApplication *)application
{
printf("********************* did enter background\n");
- OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
+ 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
@@ -282,8 +288,12 @@ static int frame_count = 0;
printf("********************* mobile app tracker found\n");
[MobileAppTracker measureSession];
#endif
- OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
+ 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 2065d459cd..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'),
]
@@ -34,9 +33,7 @@ def get_opts():
def get_flags():
return [
- ('lua', 'no'),
('tools', 'no'),
- ('nedmalloc', 'no'),
('webp', 'yes'),
('openssl','builtin'), #use builtin openssl
]
@@ -47,10 +44,6 @@ def configure(env):
env.Append(CPPPATH=['#platform/iphone', '#platform/iphone/include'])
- env['OBJSUFFIX'] = ".iphone.o"
- env['LIBSUFFIX'] = ".iphone.a"
- env['PROGSUFFIX'] = ".iphone"
-
env['ENV']['PATH'] = env['IPHONEPATH']+"/Developer/usr/bin/:"+env['ENV']['PATH']
# env['CC'] = '$IPHONEPATH/Developer/usr/bin/gcc'
@@ -60,20 +53,35 @@ 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',
+ #'-stdlib=libc++',
+ '-framework', 'Foundation',
+ '-framework', 'UIKit',
+ '-framework', 'CoreGraphics',
+ '-framework', 'OpenGLES',
+ '-framework', 'QuartzCore',
+ '-framework', 'CoreAudio',
+ '-framework', 'AudioToolbox',
+ '-framework', 'SystemConfiguration',
+ '-framework', 'Security',
+ #'-framework', 'AdSupport',
+ '-framework', 'MediaPlayer',
+ '-framework', 'AVFoundation',
+ '-framework', 'CoreMedia',
+ ])
+ else:
+ env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=4.3',
'-isysroot', '$IPHONESDK',
- #'-mmacosx-version-min=10.5',
'-framework', 'Foundation',
'-framework', 'UIKit',
'-framework', 'CoreGraphics',
@@ -85,6 +93,8 @@ def configure(env):
'-framework', 'Security',
#'-framework', 'AdSupport',
'-framework', 'MediaPlayer',
+ '-framework', 'AVFoundation',
+ '-framework', 'CoreMedia',
])
if env['game_center'] == 'yes':
@@ -99,17 +109,13 @@ 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['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
+ 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'])
env.Append(LINKFLAGS=['-Os', '-ffast-math'])
env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ENABLED'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="debug"):
@@ -123,16 +129,17 @@ 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:
env.Append(CPPFLAGS=['-fno-exceptions'])
#env['neon_enabled']=True
env['S_compiler'] = '$IPHONEPATH/Developer/usr/bin/gcc'
-
- if env['lua'] == "yes":
- env.Append(CCFLAGS=['-DLUA_USE_FLOAT'])
+
+ import methods
+ env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
-# /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..8ae7c2f87d 100755
--- a/platform/iphone/gl_view.h
+++ b/platform/iphone/gl_view.h
@@ -32,6 +32,7 @@
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#import <MediaPlayer/MediaPlayer.h>
+#import <AVFoundation/AVFoundation.h>
@protocol GLViewDelegate;
@@ -66,6 +67,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;
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index 06b679c305..bee01d3c72 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,114 @@ 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.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 +307,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])
{
@@ -326,6 +414,11 @@ static void clear_touches() {
active = TRUE;
printf("start animation!\n");
animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];
+
+ if (video_playing)
+ {
+ _unpause_video();
+ }
}
- (void)stopAnimation
@@ -337,6 +430,11 @@ static void clear_touches() {
[animationTimer invalidate];
animationTimer = nil;
clear_touches();
+
+ if (video_playing)
+ {
+ // save position
+ }
}
- (void)setAnimationInterval:(NSTimeInterval)interval
@@ -375,9 +473,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
@@ -523,6 +623,32 @@ 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;
+ }
+ }
+}
+
+- (void)playerItemDidReachEnd:(NSNotification *)notification {
+ _stop_video();
+}
+
+/*
- (void)moviePlayBackDidFinish:(NSNotification*)notification {
@@ -557,5 +683,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..aee5f76684 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;
@@ -485,13 +488,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 +517,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..cb294d07eb 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -184,9 +184,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..8d60e30d25 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}7.1.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/SCsub b/platform/javascript/SCsub
index fd1bb39e90..c1ba0c2283 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -6,8 +6,6 @@ javascript_files = [
"javascript_main.cpp"
]
-#env.Depends('#core/math/vector3.h', 'vector3_psp.h')
-
#obj = env.SharedObject('godot_javascript.cpp')
env_javascript = env.Clone()
@@ -22,4 +20,4 @@ prog = None
#env_javascript.SharedLibrary("#platform/javascript/libgodot_javascript.so",[javascript_objects])
-env.Program('#bin/godot.html', javascript_objects)
+env.Program('#bin/godot',javascript_objects,PROGSUFFIX=env["PROGSUFFIX"]+".html")
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index e4cdaad313..845b2e3395 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -46,11 +46,7 @@ def get_flags():
def configure(env):
- env.Append(CPPPATH=['#platform/android'])
-
- env['OBJSUFFIX'] = ".js.o"
- env['LIBSUFFIX'] = ".js.a"
- env['PROGSUFFIX'] = ".html"
+ env.Append(CPPPATH=['#platform/javascript'])
em_path=os.environ["EMSCRIPTEN_ROOT"]
@@ -68,17 +64,12 @@ def configure(env):
if (env["target"]=="release"):
env.Append(CCFLAGS=['-O2'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="release_debug"):
env.Append(CCFLAGS=['-O2','-DDEBUG_ENABLED'])
- env['OBJSUFFIX'] = "_optd"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_optd"+env['LIBSUFFIX']
elif (env["target"]=="debug"):
-
env.Append(CCFLAGS=['-D_DEBUG', '-Wall', '-O2', '-DDEBUG_ENABLED'])
env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC'])
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/SCsub b/platform/osx/SCsub
index d7839d7d65..4904636afd 100644
--- a/platform/osx/SCsub
+++ b/platform/osx/SCsub
@@ -8,4 +8,4 @@ files = [
# 'context_gl_osx.cpp',
]
-env.Program('#bin/godot_osx',files)
+env.Program('#bin/godot',files)
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 5337416074..141a876657 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -38,42 +38,30 @@ def configure(env):
env.Append(CPPPATH=['#platform/osx'])
- if (env["tools"]=="no"):
- #no tools suffix
- env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
+ if (env["bits"]=="default"):
+ env["bits"]="32"
if (env["target"]=="release"):
env.Append(CCFLAGS=['-O2','-ffast-math','-fomit-frame-pointer','-ftree-vectorize','-msse2'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="release_debug"):
env.Append(CCFLAGS=['-O2','-DDEBUG_ENABLED'])
- env['OBJSUFFIX'] = "_optd"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_optd"+env['LIBSUFFIX']
elif (env["target"]=="debug"):
env.Append(CCFLAGS=['-g3', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
- elif (env["target"]=="profile"):
- env.Append(CCFLAGS=['-g','-pg'])
- env.Append(LINKFLAGS=['-pg'])
-
if (env["freetype"]!="no"):
env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
env.Append(CPPPATH=['#tools/freetype'])
env.Append(CPPPATH=['#tools/freetype/freetype/include'])
- if (env["force_64_bits"]!="no"):
+ if (env["bits"]=="64"):
env.Append(CCFLAGS=['-arch', 'x86_64'])
env.Append(LINKFLAGS=['-arch', 'x86_64'])
- env['OBJSUFFIX'] = ".64"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".64"+env['LIBSUFFIX']
else:
env.Append(CCFLAGS=['-arch', 'i386'])
env.Append(LINKFLAGS=['-arch', 'i386'])
@@ -90,7 +78,7 @@ 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'])
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 5df85bca2a..24f7115938 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -156,6 +156,8 @@ public:
virtual String get_executable_path() const;
+ virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
+
virtual void move_window_to_foreground();
void run();
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index c09dadc066..5bc47a74c1 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>
@@ -694,7 +696,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 +742,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 +837,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];
@@ -1007,6 +1022,8 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
}
void OS_OSX::finalize() {
+ CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL);
+
}
void OS_OSX::set_main_loop( MainLoop * p_main_loop ) {
@@ -1070,7 +1087,20 @@ bool OS_OSX::is_mouse_grab_enabled() const {
void OS_OSX::warp_mouse_pos(const Point2& p_to) {
-//not done, must be done
+ //copied from windows impl with osx native calls
+ if (mouse_mode == MOUSE_MODE_CAPTURED){
+ mouse_x = p_to.x;
+ mouse_y = p_to.y;
+ }
+ else{ //set OS position
+ CGPoint lMouseWarpPos = {p_to.x, p_to.y};
+
+ CGEventSourceRef lEventRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
+ CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0);
+ CGAssociateMouseAndMouseCursorPosition(false);
+ CGWarpMouseCursorPosition(lMouseWarpPos);
+ CGAssociateMouseAndMouseCursorPosition(true);
+ }
}
Point2 OS_OSX::get_mouse_pos() const {
@@ -1228,6 +1258,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() {
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 682c6d0729..24b36d3188 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -41,50 +41,36 @@ def configure(env):
env["CXX"]="clang++"
env["LD"]="clang++"
- env['OBJSUFFIX'] = ".srv"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".srv"+env['LIBSUFFIX']
+ is64=sys.maxsize > 2**32
- if (env["force_32_bits"]!="no"):
- env['OBJSUFFIX'] = ".32"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".32"+env['LIBSUFFIX']
+ if (env["bits"]=="default"):
+ if (is64):
+ env["bits"]="64"
+ else:
+ env["bits"]="32"
- if (env["tools"]=="no"):
- #no tools suffix
- env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
+ #if (env["tools"]=="no"):
+ # #no tools suffix
+ # env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
+ # env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
if (env["target"]=="release"):
-
+
env.Append(CCFLAGS=['-O2','-ffast-math','-fomit-frame-pointer'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="release_debug"):
env.Append(CCFLAGS=['-O2','-ffast-math','-DDEBUG_ENABLED'])
- env['OBJSUFFIX'] = "_optd"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_optd"+env['LIBSUFFIX']
-
elif (env["target"]=="debug"):
-
- env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
- elif (env["target"]=="profile"):
-
- env.Append(CCFLAGS=['-g','-pg'])
- env.Append(LINKFLAGS=['-pg'])
+ env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
-
env.Append(CPPFLAGS=['-DSERVER_ENABLED','-DUNIX_ENABLED'])
env.Append(LIBS=['pthread','z']) #TODO detect linux/BSD!
- if (env["force_32_bits"]=="yes"):
- env.Append(CPPFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-m32','-L/usr/lib/i386-linux-gnu'])
-
if (env["CXX"]=="clang++"):
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
env["CC"]="clang"
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index 1d454e40c2..a77428e954 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -7,7 +7,8 @@ common_win=[
"ctxgl_procaddr.cpp",
"key_mapping_win.cpp",
"tcp_server_winsock.cpp",
+ "packet_peer_udp_winsock.cpp",
"stream_peer_winsock.cpp",
]
-env.Program('#bin/godot.exe',['godot_win.cpp']+common_win)
+env.Program('#bin/godot',['godot_win.cpp']+common_win,PROGSUFFIX=env["PROGSUFFIX"])
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 3277884165..16dd695c59 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -25,26 +25,38 @@ def can_build():
if (os.name=="posix"):
-
- if os.system("i586-mingw32msvc-gcc --version") == 0:
+
+ 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")
+
+ if os.system(mingw+"gcc --version >/dev/null") == 0 or os.system(mingw64+"gcc --version >/dev/null") ==0:
return True
+
return False
def get_opts():
- mwp=""
- mwp64=""
+ mingw=""
+ mingw64=""
if (os.name!="nt"):
- mwp="i586-mingw32msvc-"
- mwp64="x86_64-w64-mingw32-"
+ 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")
+
return [
- ('force_64_bits','Force 64 bits binary','no'),
- ('force_32_bits','Force 32 bits binary','no'),
- ('mingw_prefix','Mingw Prefix',mwp),
- ('mingw_prefix_64','Mingw Prefix 64 bits',mwp64),
+ ('mingw_prefix','Mingw Prefix',mingw),
+ ('mingw_prefix_64','Mingw Prefix 64 bits',mingw64),
+ ('mingw64_for_32','Use Mingw 64 for 32 Bits Build',"no"),
]
def get_flags():
@@ -52,25 +64,15 @@ def get_flags():
return [
('freetype','builtin'), #use builtin freetype
('openssl','builtin'), #use builtin openssl
+ ('theora','no'),
]
def configure(env):
- if os.name == "posix":
- env['OBJSUFFIX'] = ".win"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".win"+env['LIBSUFFIX']
-
env.Append(CPPPATH=['#platform/windows'])
- if (env["tools"]=="no"):
- #no tools suffix
- env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
- #env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
- env['platform_libsuffix'] = ".nt"+env['LIBSUFFIX']
-
-
if (os.name=="nt" and os.getenv("VSINSTALLDIR")!=None):
#build using visual studio
@@ -89,21 +91,17 @@ def configure(env):
env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
- elif (env["target"]=="test"):
+ elif (env["target"]=="release_debug"):
- env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
+ env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED'])
env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
elif (env["target"]=="debug"):
- env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO','/O1'])
+ env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DDEBUG_MEMORY_ENABLED','/DD3D_DEBUG_INFO','/O1'])
env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
env.Append(LINKFLAGS=['/DEBUG'])
- elif (env["target"]=="profile"):
-
- env.Append(CCFLAGS=['-g','-pg'])
- env.Append(LINKFLAGS=['-pg'])
env.Append(CCFLAGS=['/MT','/Gd','/GR','/nologo'])
env.Append(CXXFLAGS=['/TP'])
@@ -115,9 +113,10 @@ def configure(env):
env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
- env.Append(CCFLAGS=['/DGLES1_ENABLED'])
+
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
- env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32'])
+ LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32']
+ env.Append(LINKFLAGS=[p+env["LIBSUFFIX"] for p in LIBS])
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
if (os.getenv("DXSDK_DIR")):
@@ -136,50 +135,81 @@ 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 mySpawn(sh, escape, cmd, args, env):
+ newargs = ' '.join(args[1:])
+ cmdline = cmd + " " + newargs
+ 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
+ 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"
mingw_prefix=""
- if (env["force_32_bits"]!="no"):
- env['OBJSUFFIX'] = ".32"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".32"+env['LIBSUFFIX']
- env.Append(CCFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-static-libgcc'])
- env.Append(LINKFLAGS=['-static-libstdc++'])
+ 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"];
- if (env["force_64_bits"]!="no"):
+ else:
mingw_prefix=env["mingw_prefix_64"];
- env['OBJSUFFIX'] = ".64"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".64"+env['LIBSUFFIX']
env.Append(LINKFLAGS=['-static'])
+
+ nulstr=""
+
+ if (os.name=="posix"):
+ nulstr=">/dev/null"
else:
- mingw_prefix=env["mingw_prefix"];
+ nulstr=">nul"
+
+
+
+ if os.system(mingw_prefix+"gcc --version"+nulstr)!=0:
+ #not really super consistent but..
+ print("Can't find Windows compiler: "+mingw_prefix)
+ sys.exit(255)
if (env["target"]=="release"):
env.Append(CCFLAGS=['-O3','-ffast-math','-fomit-frame-pointer','-msse2'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
+
elif (env["target"]=="release_debug"):
env.Append(CCFLAGS=['-O2','-DDEBUG_ENABLED'])
- env['OBJSUFFIX'] = "_optd"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_optd"+env['LIBSUFFIX']
elif (env["target"]=="debug"):
- env.Append(CCFLAGS=['-g', '-Wall','-DDEBUG_ENABLED'])
- elif (env["target"]=="release_tools"):
-
- env.Append(CCFLAGS=['-O2','-Wall','-DDEBUG_ENABLED'])
-
+ env.Append(CCFLAGS=['-g', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
if (env["freetype"]!="no"):
env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
@@ -198,8 +228,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(CCFLAGS=['-DGLES2_ENABLED','-DGLEW_ENABLED'])
env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
+
+ if (env["bits"]=="32" and env["mingw64_for_32"]!="yes"):
+# 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..45d13da828 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,18 @@
#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"
static const WORD MAX_CONSOLE_LINES = 1500;
+
//#define STDOUT_FILE
extern HINSTANCE godot_hinstance;
@@ -126,11 +130,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 {
@@ -173,6 +177,7 @@ void OS_Windows::initialize_core() {
TCPServerWinsock::make_default();
StreamPeerWinsock::make_default();
+ PacketPeerUDPWinsock::make_default();
mempool_static = new MemoryPoolStaticMalloc;
#if 1
@@ -928,7 +933,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);
@@ -982,8 +987,11 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
DEVMODE current;
memset(&current,0,sizeof(current));
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &current);
+
+ 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 +1003,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
if (err!=DISP_CHANGE_SUCCESSFUL) {
video_mode.fullscreen=false;
- }
+ }*/
}
DWORD dwExStyle;
@@ -1388,8 +1396,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;
@@ -1489,7 +1498,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;
@@ -1870,7 +1879,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..20993c6419 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -249,6 +249,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 c83f4fab32..2ea8cbd0de 100644
--- a/platform/winrt/SCsub
+++ b/platform/winrt/SCsub
@@ -3,6 +3,9 @@ Import('env')
files = [
'thread_winrt.cpp',
# '#platform/windows/stream_peer_winsock.cpp',
+ 'gl_context_egl.cpp',
+ 'app.cpp',
+ 'os_winrt.cpp',
]
-env.Program('#bin/godot_rt.exe', files)
+env.Program('#bin/godot', files)
diff --git a/platform/winrt/app.cpp b/platform/winrt/app.cpp
new file mode 100644
index 0000000000..662229b04e
--- /dev/null
+++ b/platform/winrt/app.cpp
@@ -0,0 +1,385 @@
+//
+// This file demonstrates how to initialize EGL in a Windows Store app, using ICoreWindow.
+//
+
+#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;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Input;
+using namespace Windows::Foundation;
+using namespace Windows::Graphics::Display;
+using namespace Microsoft::WRL;
+using namespace Platform;
+
+using namespace $ext_safeprojectname$;
+
+// Helper to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
+inline float ConvertDipsToPixels(float dips, float dpi)
+{
+ static const float dipsPerInch = 96.0f;
+ return floor(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
+}
+
+// Implementation of the IFrameworkViewSource interface, necessary to run our app.
+ref class HelloTriangleApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
+{
+public:
+ virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView()
+ {
+ return ref new App();
+ }
+};
+
+// The main function creates an IFrameworkViewSource for our app, and runs the app.
+[Platform::MTAThread]
+int main(Platform::Array<Platform::String^>^)
+{
+ auto helloTriangleApplicationSource = ref new HelloTriangleApplicationSource();
+ CoreApplication::Run(helloTriangleApplicationSource);
+ return 0;
+}
+
+App::App() :
+ mWindowClosed(false),
+ mWindowVisible(true),
+ mWindowWidth(0),
+ mWindowHeight(0),
+ mEglDisplay(EGL_NO_DISPLAY),
+ mEglContext(EGL_NO_CONTEXT),
+ mEglSurface(EGL_NO_SURFACE)
+{
+}
+
+// The first method called when the IFrameworkView is being created.
+void App::Initialize(CoreApplicationView^ applicationView)
+{
+ // Register event handlers for app lifecycle. This example includes Activated, so that we
+ // can make the CoreWindow active and start rendering on the window.
+ applicationView->Activated +=
+ ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
+
+ // Logic for other event handlers could go here.
+ // Information about the Suspending and Resuming event handlers can be found here:
+ // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx
+
+ os = new OSWinrt;
+}
+
+// Called when the CoreWindow object is created (or re-created).
+void App::SetWindow(CoreWindow^ p_window)
+{
+ window = p_window;
+ window->VisibilityChanged +=
+ ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
+
+ window->Closed +=
+ ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
+
+ window->SizeChanged +=
+ ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
+
+#if !(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ // Disable all pointer visual feedback for better performance when touching.
+ // This is not supported on Windows Phone applications.
+ auto pointerVisualizationSettings = PointerVisualizationSettings::GetForCurrentView();
+ pointerVisualizationSettings->IsContactFeedbackEnabled = false;
+ pointerVisualizationSettings->IsBarrelButtonFeedbackEnabled = false;
+#endif
+
+
+ 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));
+
+ 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[] = {"-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();
+}
+
+// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
+// class is torn down while the app is in the foreground.
+void App::Uninitialize()
+{
+ Main::cleanup();
+ delete os;
+}
+
+// Application lifecycle event handler.
+void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
+{
+ // Run() won't start until the CoreWindow is activated.
+ CoreWindow::GetForCurrentThread()->Activate();
+}
+
+// Window event handlers.
+void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
+{
+ mWindowVisible = args->Visible;
+}
+
+void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
+{
+ mWindowClosed = true;
+}
+
+void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
+{
+#if (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
+ // On Windows 8.1, apps are resized when they are snapped alongside other apps, or when the device is rotated.
+ // The default framebuffer will be automatically resized when either of these occur.
+ // In particular, on a 90 degree rotation, the default framebuffer's width and height will switch.
+ UpdateWindowSize(args->Size);
+#else if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ // 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)
+{
+ 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
new file mode 100644
index 0000000000..7926465ff8
--- /dev/null
+++ b/platform/winrt/app.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <string>
+
+#include <wrl.h>
+
+#include "os_winrt.h"
+#include "GLES2/gl2.h"
+
+namespace $ext_safeprojectname$
+{
+ ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
+ {
+ public:
+ App();
+
+ // IFrameworkView Methods.
+ virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
+ virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
+ virtual void Load(Platform::String^ entryPoint);
+ virtual void Run();
+ virtual void Uninitialize();
+
+ private:
+ void RecreateRenderer();
+
+ // Application lifecycle event handlers.
+ void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
+
+ // Window event handlers.
+ void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
+ 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();
+
+ bool mWindowClosed;
+ bool mWindowVisible;
+ GLsizei mWindowWidth;
+ GLsizei mWindowHeight;
+
+ 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 d09688b71c..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', '/ZW', '/EHsc'])
- env.Append(CXXFLAGS=['/TP'])
- 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'])
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
new file mode 100644
index 0000000000..fd9fbe406f
--- /dev/null
+++ b/platform/winrt/gl_context_egl.cpp
@@ -0,0 +1,177 @@
+#include "gl_context_egl.h"
+
+#include "EGL/eglext.h"
+
+using namespace Platform;
+
+void ContextEGL::release_current() {
+
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEglContext);
+};
+
+void ContextEGL::make_current() {
+
+ eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
+};
+
+int ContextEGL::get_window_width() {
+
+ return width;
+};
+
+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)
+ {
+ cleanup();
+
+ window = CoreWindow::GetForCurrentThread();
+ initialize();
+
+ // tell rasterizer to reload textures and stuff?
+ }
+};
+
+Error ContextEGL::initialize() {
+
+ EGLint configAttribList[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 8,
+ EGL_STENCIL_SIZE, 8,
+ EGL_SAMPLE_BUFFERS, 0,
+ EGL_NONE
+ };
+
+ EGLint surfaceAttribList[] = {
+ EGL_NONE, EGL_NONE
+ };
+
+ EGLint numConfigs = 0;
+ EGLint majorVersion = 1;
+ EGLint minorVersion = 0;
+ EGLDisplay display = EGL_NO_DISPLAY;
+ EGLContext context = EGL_NO_CONTEXT;
+ EGLSurface surface = EGL_NO_SURFACE;
+ EGLConfig config = nullptr;
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+ try {
+
+ 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");
+ }
+
+ if (eglInitialize(display, &majorVersion, &minorVersion) == EGL_FALSE)
+ {
+ throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL");
+ }
+
+ if (eglGetConfigs(display, NULL, 0, &numConfigs) == EGL_FALSE)
+ {
+ throw Exception::CreateException(E_FAIL, L"Failed to get EGLConfig count");
+ }
+
+ if (eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) == EGL_FALSE)
+ {
+ throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig count");
+ }
+
+ surface = eglCreateWindowSurface(display, config, reinterpret_cast<IInspectable*>(window), surfaceAttribList);
+ if (surface == EGL_NO_SURFACE)
+ {
+ throw Exception::CreateException(E_FAIL, L"Failed to create EGL fullscreen surface");
+ }
+
+ context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
+ if (context == EGL_NO_CONTEXT)
+ {
+ throw Exception::CreateException(E_FAIL, L"Failed to create EGL context");
+ }
+
+ if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
+ {
+ throw Exception::CreateException(E_FAIL, L"Failed to make fullscreen EGLSurface current");
+ }
+ } catch (...) {
+ return FAILED;
+ };
+
+ mEglDisplay = display;
+ mEglSurface = surface;
+ mEglContext = context;
+
+ eglQuerySurface(display,surface,EGL_WIDTH,&width);
+ eglQuerySurface(display,surface,EGL_HEIGHT,&height);
+
+ return OK;
+};
+
+void ContextEGL::cleanup() {
+
+ if (mEglDisplay != EGL_NO_DISPLAY && mEglSurface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ mEglSurface = EGL_NO_SURFACE;
+ }
+
+ if (mEglDisplay != EGL_NO_DISPLAY && mEglContext != EGL_NO_CONTEXT)
+ {
+ eglDestroyContext(mEglDisplay, mEglContext);
+ mEglContext = EGL_NO_CONTEXT;
+ }
+
+ if (mEglDisplay != EGL_NO_DISPLAY)
+ {
+ eglTerminate(mEglDisplay);
+ mEglDisplay = EGL_NO_DISPLAY;
+ }
+};
+
+ContextEGL::ContextEGL(CoreWindow^ p_window) :
+ mEglDisplay(EGL_NO_DISPLAY),
+ mEglContext(EGL_NO_CONTEXT),
+ mEglSurface(EGL_NO_SURFACE)
+ {
+
+ window = p_window;
+};
+
+ContextEGL::~ContextEGL() {
+
+ cleanup();
+};
+
diff --git a/platform/winrt/gl_context_egl.h b/platform/winrt/gl_context_egl.h
new file mode 100644
index 0000000000..ca3760e723
--- /dev/null
+++ b/platform/winrt/gl_context_egl.h
@@ -0,0 +1,45 @@
+#ifndef CONTEXT_EGL_H
+#define CONTEXT_EGL_H
+
+#include <wrl.h>
+
+#include "os/os.h"
+#include "EGL/egl.h"
+#include "error_list.h"
+#include "drivers/gl_context/context_gl.h"
+
+using namespace Windows::UI::Core;
+
+class ContextEGL : public ContextGL {
+
+ CoreWindow^ window;
+
+ EGLDisplay mEglDisplay;
+ EGLContext mEglContext;
+ EGLSurface mEglSurface;
+
+ EGLint width;
+ EGLint height;
+
+public:
+
+ virtual void release_current();
+
+ virtual void make_current();
+
+ virtual int get_window_width();
+ virtual int get_window_height();
+ virtual void swap_buffers();
+
+ virtual Error initialize();
+ void reset();
+
+ void cleanup();
+
+ ContextEGL(CoreWindow^ p_window);
+ ~ContextEGL();
+
+};
+
+#endif
+
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 16a74c877c..89fa93c5c4 100644
--- a/platform/winrt/os_winrt.cpp
+++ b/platform/winrt/os_winrt.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* os_windows.cpp */
+/* os_winrt.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,12 +28,12 @@
/*************************************************************************/
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles1/rasterizer_gles1.h"
-#include "os_windows.h"
+#include "os_winrt.h"
#include "drivers/nedmalloc/memory_pool_static_nedmalloc.h"
#include "drivers/unix/memory_pool_static_malloc.h"
#include "os/memory_pool_dynamic_static.h"
-#include "drivers/windows/thread_windows.h"
-#include "drivers/windows/semaphore_windows.h"
+#include "thread_winrt.h"
+//#include "drivers/windows/semaphore_windows.h"
#include "drivers/windows/mutex_windows.h"
#include "main/main.h"
#include "drivers/windows/file_access_windows.h"
@@ -44,14 +44,22 @@
#include "servers/audio/audio_server_sw.h"
#include "servers/visual/visual_server_wrap_mt.h"
-#include "tcp_server_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 <wrl.h>
+
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Input;
+using namespace Windows::Foundation;
+using namespace Windows::Graphics::Display;
+using namespace Microsoft::WRL;
+
+
int OSWinrt::get_video_driver_count() const {
return 2;
@@ -63,7 +71,7 @@ const char * OSWinrt::get_video_driver_name(int p_driver) const {
OS::VideoMode OSWinrt::get_default_video_mode() const {
- return VideoMode(800,600,false);
+ return video_mode;
}
int OSWinrt::get_audio_driver_count() const {
@@ -129,59 +137,33 @@ bool OSWinrt::can_draw() const {
};
-void OSWinrt::_touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam) {
-
- InputEvent event;
- event.type = InputEvent::SCREEN_TOUCH;
- event.ID=++last_id;
- event.screen_touch.index = idx;
-
- switch (uMsg) {
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN: {
-
- event.screen_touch.pressed = true;
- } break;
+void OSWinrt::set_gl_context(ContextEGL* p_context) {
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP: {
- event.screen_touch.pressed = false;
- } break;
- };
-
- event.screen_touch.x=GET_X_LPARAM(lParam);
- event.screen_touch.y=GET_Y_LPARAM(lParam);
-
- if (main_loop) {
- input->parse_input_event(event);
- }
+ gl_context = p_context;
};
-void OSWinrt::_drag_event(int idx,UINT uMsg, WPARAM wParam, LPARAM lParam) {
+void OSWinrt::screen_size_changed() {
- InputEvent event;
- event.type = InputEvent::SCREEN_DRAG;
- event.ID=++last_id;
- event.screen_drag.index = idx;
-
- event.screen_drag.x=GET_X_LPARAM(lParam);
- event.screen_drag.y=GET_Y_LPARAM(lParam);
-
- if (main_loop)
- input->parse_input_event(event);
+ 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) {
@@ -222,6 +204,7 @@ void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_aud
void OSWinrt::set_clipboard(const String& p_text) {
+ /*
if (!OpenClipboard(hWnd)) {
ERR_EXPLAIN("Unable to open clipboard.");
ERR_FAIL();
@@ -255,10 +238,12 @@ void OSWinrt::set_clipboard(const String& p_text) {
SetClipboardData(CF_TEXT, mem);
CloseClipboard();
+ */
};
String OSWinrt::get_clipboard() const {
+ /*
String ret;
if (!OpenClipboard(hWnd)) {
ERR_EXPLAIN("Unable to open clipboard.");
@@ -295,9 +280,16 @@ String OSWinrt::get_clipboard() const {
CloseClipboard();
return ret;
+ */
+ return "";
};
+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)
@@ -327,10 +319,6 @@ void OSWinrt::finalize() {
if (rasterizer)
memdelete(rasterizer);
- if (user_proc) {
- SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
- };
-
spatial_sound_server->finish();
memdelete(spatial_sound_server);
spatial_sound_2d_server->finish();
@@ -355,16 +343,11 @@ void OSWinrt::finalize() {
}
void OSWinrt::finalize_core() {
- memdelete(process_map);
-
if (mempool_dynamic)
memdelete( mempool_dynamic );
if (mempool_static)
delete mempool_static;
-
- TCPServerWinsock::cleanup();
- StreamPeerWinsock::cleanup();
}
void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
@@ -399,10 +382,7 @@ void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
void OSWinrt::alert(const String& p_alert,const String& p_title) {
- if (!is_no_window_mode_enabled())
- MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
- else
- print_line("ALERT: "+p_alert);
+ print_line("ALERT: "+p_alert);
}
void OSWinrt::set_mouse_mode(MouseMode p_mode) {
@@ -432,7 +412,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 {
@@ -445,71 +425,16 @@ void OSWinrt::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) con
void OSWinrt::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);
- if (!hCon || hCon==INVALID_HANDLE_VALUE) {
- if (p_rationale && p_rationale[0]) {
+ if (p_rationale && p_rationale[0]) {
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+ print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
+ print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
- } else {
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
-
- }
} else {
+ print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
+ print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
- CONSOLE_SCREEN_BUFFER_INFO sbi; //original
- GetConsoleScreenBufferInfo(hCon,&sbi);
-
- SetConsoleTextAttribute(hCon,sbi.wAttributes);
-
-
-
- uint32_t basecol=0;
- switch(p_type) {
- case ERR_ERROR: basecol = FOREGROUND_RED; break;
- case ERR_WARNING: basecol = FOREGROUND_RED|FOREGROUND_GREEN; break;
- case ERR_SCRIPT: basecol = FOREGROUND_GREEN; break;
- }
-
- if (p_rationale && p_rationale[0]) {
-
- SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
-
-
- switch(p_type) {
- case ERR_ERROR: print("ERROR: "); break;
- case ERR_WARNING: print("WARNING: "); break;
- case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
- }
-
- SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
- print(" %s\n",p_rationale);
- SetConsoleTextAttribute(hCon,basecol);
- print("At: ");
- SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
- print(" %s:%i\n",p_file,p_line);
-
-
- } else {
- SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
- switch(p_type) {
- case ERR_ERROR: print("ERROR: %s: ",p_function); break;
- case ERR_WARNING: print("WARNING: %s: ",p_function); break;
- case ERR_SCRIPT: print("SCRIPT ERROR: %s: ",p_function); break;
- }
- SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
- print(" %s\n",p_code);
- SetConsoleTextAttribute(hCon,basecol);
- print("At: ");
- SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
- print(" %s:%i\n",p_file,p_line);
- }
-
- SetConsoleTextAttribute(hCon,sbi.wAttributes);
}
-
}
@@ -566,10 +491,10 @@ uint64_t OSWinrt::get_unix_time() const {
void OSWinrt::delay_usec(uint32_t p_usec) const {
- if (p_usec < 1000)
- Sleep(1);
- else
- Sleep(p_usec / 1000);
+ int msec = p_usec < 1000 ? 1 : p_usec / 1000;
+
+ // no Sleep()
+ WaitForSingleObjectEx(GetCurrentThread(), msec, false);
}
uint64_t OSWinrt::get_ticks_usec() const {
@@ -607,19 +532,12 @@ Error OSWinrt::kill(const ProcessID& p_pid) {
Error OSWinrt::set_cwd(const String& p_cwd) {
- if (_wchdir(p_cwd.c_str())!=0)
- return ERR_CANT_OPEN;
-
- return OK;
+ return FAILED;
}
String OSWinrt::get_executable_path() const {
- wchar_t bufname[4096];
- GetModuleFileNameW(NULL,bufname,4096);
- String s= bufname;
- print_line("EXEC PATHPó: "+s);
- return s;
+ return "";
}
void OSWinrt::set_icon(const Image& p_icon) {
@@ -629,25 +547,16 @@ void OSWinrt::set_icon(const Image& p_icon) {
bool OSWinrt::has_environment(const String& p_var) const {
- return getenv(p_var.utf8().get_data()) != NULL;
+ return false;
};
String OSWinrt::get_environment(const String& p_var) const {
- char* val = getenv(p_var.utf8().get_data());
- if (val)
- return val;
-
return "";
};
String OSWinrt::get_stdin_string(bool p_block) {
- if (p_block) {
- char buff[1024];
- return fgets(buff,1024,stdin);
- };
-
return String();
}
@@ -664,24 +573,27 @@ 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();
+ return language->Data();
+#endif
}
void OSWinrt::release_rendering_thread() {
- //gl_context->release_current();
-
+ gl_context->release_current();
}
void OSWinrt::make_rendering_thread() {
- //gl_context->make_current();
+ gl_context->make_current();
}
void OSWinrt::swap_buffers() {
- //gl_context->swap_buffers();
+ gl_context->swap_buffers();
}
@@ -699,6 +611,7 @@ void OSWinrt::run() {
while (!force_quit) {
+ CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
process_events(); // get rid of pending events
if (Main::iteration()==true)
break;
@@ -724,7 +637,7 @@ String OSWinrt::get_data_dir() const {
}
-OSWinrt::OSWinrt(HINSTANCE _hInstance) {
+OSWinrt::OSWinrt() {
key_event_pos=0;
force_quit=false;
@@ -743,6 +656,9 @@ OSWinrt::OSWinrt(HINSTANCE _hInstance) {
stdo=fopen("stdout.txt","wb");
#endif
+ gl_context = NULL;
+
+ AudioDriverManagerSW::add_driver(&audio_driver);
}
diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h
index bc7e188c20..68236309a9 100644
--- a/platform/winrt/os_winrt.h
+++ b/platform/winrt/os_winrt.h
@@ -40,12 +40,12 @@
#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"
#include <windows.h>
-#include "key_mapping_win.h"
-#include <windowsx.h>
#include <io.h>
#include <fcntl.h>
@@ -93,6 +93,8 @@ class OSWinrt : public OS {
Physics2DServer *physics_2d_server;
int pressrc;
+ ContextEGL* gl_context;
+
struct Joystick {
int id;
@@ -123,6 +125,7 @@ class OSWinrt : public OS {
MainLoop *main_loop;
+ AudioDriverDummy audio_driver;
AudioServerSW *audio_server;
SampleManagerMallocSW *sample_manager;
SpatialSoundServerSW *spatial_sound_server;
@@ -224,16 +227,23 @@ public:
virtual void move_window_to_foreground();
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/SCsub b/platform/x11/SCsub
index 1a552cbaac..7a6f02daa5 100644
--- a/platform/x11/SCsub
+++ b/platform/x11/SCsub
@@ -8,5 +8,3 @@ common_x11=[\
]
env.Program('#bin/godot',['godot_x11.cpp']+common_x11)
-if env['target'] == "release":
- env.Command('#bin/godot_rel', '#bin/godot', Copy('bin/godot_rel', 'bin/godot'))
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index cff7ea86b6..8264196a41 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -47,22 +47,30 @@ def get_opts():
return [
('use_llvm','Use llvm compiler','no'),
('use_sanitizer','Use llvm compiler sanitize address','no'),
- ('force_32_bits','Force 32 bits binary','no')
+ ('pulseaudio','Detect & Use pulseaudio','yes'),
]
def get_flags():
return [
- ('opengl', 'no'),
- ('legacygl', 'yes'),
('builtin_zlib', 'no'),
("openssl", "yes"),
+ ("theora","no"),
]
def configure(env):
+ is64=sys.maxsize > 2**32
+
+ if (env["bits"]=="default"):
+ if (is64):
+ env["bits"]="64"
+ else:
+ env["bits"]="32"
+
+
env.Append(CPPPATH=['#platform/x11'])
if (env["use_llvm"]=="yes"):
env["CC"]="clang"
@@ -71,53 +79,30 @@ def configure(env):
if (env["use_sanitizer"]=="yes"):
env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer'])
env.Append(LINKFLAGS=['-fsanitize=address'])
+ env.extra_suffix=".llvms"
+ else:
+ env.extra_suffix=".llvm"
+
- if (env["tools"]=="no"):
- #no tools suffix
- env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
+ #if (env["tools"]=="no"):
+ # #no tools suffix
+ # env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
+ # env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
if (env["target"]=="release"):
env.Append(CCFLAGS=['-O2','-ffast-math','-fomit-frame-pointer'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="release_debug"):
env.Append(CCFLAGS=['-O2','-ffast-math','-DDEBUG_ENABLED'])
- env['OBJSUFFIX'] = "_optd"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_optd"+env['LIBSUFFIX']
-
-
-# env.Append(CCFLAGS=['-Os','-ffast-math','-fomit-frame-pointer'])
-#does not seem to have much effect
-# env.Append(CCFLAGS=['-fno-default-inline'])
-#recommended by wxwidgets
-# env.Append(CCFLAGS=['-ffunction-sections','-fdata-sections'])
-# env.Append(LINKFLAGS=['-Wl','--gc-sections'])
elif (env["target"]=="debug"):
-
- env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
-#does not seem to have much effect
-# env.Append(CCFLAGS=['-fno-default-inline'])
-#recommended by wxwidgets
-# env.Append(CCFLAGS=['-ffunction-sections','-fdata-sections'])
-# env.Append(LINKFLAGS=['-Wl','--gc-sections'])
-
- elif (env["target"]=="debug_light"):
- env.Append(CCFLAGS=['-g1', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
-
-
- elif (env["target"]=="profile"):
-
- env.Append(CCFLAGS=['-g','-pg'])
- env.Append(LINKFLAGS=['-pg'])
+ env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED'])
env.ParseConfig('pkg-config x11 --cflags --libs')
env.ParseConfig('pkg-config xcursor --cflags --libs')
@@ -128,19 +113,29 @@ def configure(env):
env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
- if env['opengl'] == 'yes':
- env.Append(CPPFLAGS=['-DOPENGL_ENABLED','-DGLEW_ENABLED'])
- #env.Append(CPPFLAGS=["-DRTAUDIO_ENABLED"])
+ 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'])
-# env.Append(CPPFLAGS=['-DX11_ENABLED','-DUNIX_ENABLED','-DGLES2_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'])
- if (env["force_32_bits"]=="yes"):
+
+#host compiler is default..
+
+ if (is64 and env["bits"]=="32"):
env.Append(CPPFLAGS=['-m32'])
env.Append(LINKFLAGS=['-m32','-L/usr/lib/i386-linux-gnu'])
- env['OBJSUFFIX'] = ".32"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".32"+env['LIBSUFFIX']
+ 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++"):
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 4c45fcfaaf..a40af8d2a9 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>
@@ -63,17 +62,29 @@
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;
@@ -154,10 +165,10 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
context_gl = memnew( ContextGL_X11( x11_display, x11_window,current_videomode, false ) );
context_gl->initialize();
- if (p_video_driver == 0) {
+ if (true) {
rasterizer = memnew( RasterizerGLES2 );
} else {
- rasterizer = memnew( RasterizerGLES1 );
+ //rasterizer = memnew( RasterizerGLES1 );
};
#endif
@@ -1088,7 +1099,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();
}
@@ -1380,6 +1457,10 @@ 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
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 2ffca0e042..dd2476ec1b 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
@@ -160,7 +165,10 @@ 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();
@@ -197,6 +205,8 @@ 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);
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..fce21f6001 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,11 +210,18 @@ void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_b
}
+ 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();
@@ -212,7 +232,7 @@ void Area2D::_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++) {
@@ -222,8 +242,8 @@ void Area2D::_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);
}
}
@@ -232,7 +252,7 @@ void Area2D::_notification(int p_what) {
switch(p_what) {
- case NOTIFICATION_EXIT_SCENE: {
+ case NOTIFICATION_EXIT_TREE: {
_clear_monitoring();
} break;
@@ -243,6 +263,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;
@@ -263,11 +288,30 @@ bool Area2D::is_monitoring_enabled() const {
return monitoring;
}
+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;
+}
+
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("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 +325,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,6 +337,8 @@ 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("get_overlapping_bodies"),&Area2D::get_overlapping_bodies);
+
ObjectTypeDB::bind_method(_MD("_body_inout"),&Area2D::_body_inout);
@@ -302,7 +351,8 @@ void Area2D::_bind_methods() {
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"));
@@ -314,7 +364,9 @@ 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;
set_enable_monitoring(true);
diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h
index b4c8edf138..f770e88a19 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/area_2d.h
@@ -49,14 +49,16 @@ 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 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,7 +78,7 @@ private:
struct BodyState {
int rc;
- bool in_scene;
+ bool in_tree;
VSet<ShapePair> shapes;
};
@@ -103,8 +105,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 +117,8 @@ public:
void set_enable_monitoring(bool p_enable);
bool is_monitoring_enabled() const;
+ Array get_overlapping_bodies() const; //function for script
+
Area2D();
~Area2D();
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index fe6c9637e0..b3897010bf 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,10 +316,10 @@ 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);
}
}
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index d66f100b3f..ae857bbce9 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -38,7 +38,7 @@
bool CanvasItem::is_visible() const {
- if (!is_inside_scene())
+ if (!is_inside_tree())
return false;
const CanvasItem *p=this;
@@ -92,7 +92,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 +106,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 +147,7 @@ void CanvasItem::_update_callback() {
- if (!is_inside_scene()) {
+ if (!is_inside_tree()) {
pending_update=false;
return;
}
@@ -225,7 +225,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 +243,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 +283,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 +313,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 +324,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 +340,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 +379,7 @@ bool CanvasItem::_is_visible_() const {
void CanvasItem::update() {
- if (!is_inside_scene())
+ if (!is_inside_tree())
return;
if (pending_update)
return;
@@ -406,7 +406,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;
}
@@ -630,8 +630,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 +648,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 +677,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 +693,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 +720,95 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{
return behind;
}
+void CanvasItem::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_set_shader(canvas_item,rid);
+ _change_notify(); //properties for shader exposed
+}
+
+void CanvasItem::set_use_parent_shader(bool p_use_parent_shader) {
+
+ use_parent_shader=p_use_parent_shader;
+ VS::get_singleton()->canvas_item_set_use_parent_shader(canvas_item,p_use_parent_shader);
+}
+
+bool CanvasItem::get_use_parent_shader() const{
+
+ return use_parent_shader;
+}
+
+Ref<Shader> CanvasItem::get_shader() const{
+
+ return shader;
+}
+
+void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) {
+
+ VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value);
+}
+
+Variant CanvasItem::get_shader_param(const StringName& p_param) const {
+
+ return VS::get_singleton()->canvas_item_get_shader_param(canvas_item,p_param);
+}
+
+bool CanvasItem::_set(const StringName& p_name, const Variant& p_value) {
+
+ if (shader.is_valid()) {
+ StringName pr = shader->remap_param(p_name);
+ if (pr) {
+ set_shader_param(pr,p_value);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CanvasItem::_get(const StringName& p_name,Variant &r_ret) const{
+
+ if (shader.is_valid()) {
+ StringName pr = shader->remap_param(p_name);
+ if (pr) {
+ r_ret=get_shader_param(pr);
+ return true;
+ }
+ }
+ return false;
+
+}
+void CanvasItem::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ if (shader.is_valid()) {
+ shader->get_param_list(p_list);
+ }
+}
+
+#ifdef TOOLS_ENABLED
+void CanvasItem::_shader_changed() {
+
+ _change_notify();
+}
+#endif
void CanvasItem::_bind_methods() {
@@ -761,7 +850,9 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top);
-
+#ifdef TOOLS_ENABLED
+ ObjectTypeDB::bind_method(_MD("_shader_changed"),&CanvasItem::_shader_changed);
+#endif
//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));
@@ -786,15 +877,22 @@ void CanvasItem::_bind_methods() {
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_shader","shader"),&CanvasItem::set_shader);
+ ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader);
+ ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader);
+ ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader);
+
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::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") );
//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 +922,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 +933,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,6 +969,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
block_transform_notify=false;
// viewport=NULL;
canvas_layer=NULL;
+ use_parent_shader;
global_invalid=true;
C=NULL;
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 604eef0527..ed3ade9df2 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;
@@ -80,6 +81,9 @@ private:
bool block_transform_notify;
bool behind;
+ bool use_parent_shader;
+ Ref<Shader> shader;
+
mutable Matrix32 global_transform;
mutable bool global_invalid;
@@ -99,8 +103,9 @@ private:
void _queue_sort_children();
void _sort_children();
-
-
+#ifdef TOOLS_ENABLED
+ void _shader_changed();
+#endif
void _notify_transform(CanvasItem *p_node);
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
@@ -108,9 +113,12 @@ private:
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;
- _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 +128,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,
@@ -204,7 +212,14 @@ public:
RID get_canvas() const;
Ref<World2D> get_world_2d() const;
+ void set_shader(const Ref<Shader>& p_shader);
+ Ref<Shader> get_shader() const;
+
+ void set_use_parent_shader(bool p_use_parent_shader);
+ bool get_use_parent_shader() const;
+ void set_shader_param(const StringName& p_param,const Variant& p_value);
+ Variant get_shader_param(const StringName& p_param) const;
CanvasItem();
~CanvasItem();
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index e5d9872a28..3b859d9366 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -45,7 +45,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());
@@ -69,7 +69,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,13 +156,13 @@ 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) );
}
}
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index ef63286697..1c0be60764 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -41,7 +41,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 +50,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 +72,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);
}
@@ -95,7 +98,7 @@ void CollisionPolygon2D::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- if (!is_inside_scene())
+ if (!is_inside_tree())
break;
_update_parent();
@@ -166,6 +169,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 +190,19 @@ 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;
}
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index 09c2060088..b8e27b6fb4 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -50,6 +50,7 @@ protected:
Rect2 aabb;
BuildMode build_mode;
Vector<Point2> polygon;
+ bool trigger;
void _add_to_collision_object(Object *p_obj);
void _update_parent();
@@ -60,6 +61,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/node_2d.cpp b/scene/2d/node_2d.cpp
index 4c00db2429..8b4196ee7f 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -130,7 +130,7 @@ void Node2D::_update_transform() {
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),_mat);
- if (!is_inside_scene())
+ if (!is_inside_tree())
return;
@@ -272,7 +272,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 +289,35 @@ 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;
+}
+
+
void Node2D::_bind_methods() {
@@ -308,18 +337,25 @@ void Node2D::_bind_methods() {
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("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);
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"));
}
@@ -331,6 +367,8 @@ Node2D::Node2D() {
angle=0;
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..61b8c829d6 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -38,6 +38,8 @@ class Node2D : public CanvasItem {
Point2 pos;
float angle;
Size2 scale;
+ int z;
+ bool z_relative;
Matrix32 _mat;
@@ -85,6 +87,11 @@ 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_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 ded86702ef..6e2cf5954b 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;
}
@@ -507,7 +515,13 @@ void Particles2D::_notification(int p_what) {
}
- for(int i=0;i<particle_count;i++) {
+ int start_particle = (int)(time * (float)particle_count / lifetime);
+
+ for (int id=0;id<particle_count;++id) {
+ int i = start_particle + id;
+ if (i >= particle_count) {
+ i -= particle_count;
+ }
Particle &p=pdata[i];
if (!p.active)
@@ -606,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);
@@ -636,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]={
@@ -653,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]={
@@ -670,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",
};
@@ -903,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) {
@@ -952,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);
@@ -991,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++) {
@@ -1048,6 +1109,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;
@@ -1075,6 +1137,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 78b5e23da0..6f18325212 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,7 @@ 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);
}
@@ -198,7 +230,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 +250,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;
@@ -250,18 +282,19 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
if (!E) {
E = contact_monitor->body_map.insert(objid,BodyState());
- E->get().rc=0;
- E->get().in_scene=node && node->is_inside_scene();
+// E->get().rc=0;
+ 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);
}
}
+ //E->get().rc++;
}
- E->get().rc++;
+
if (node)
E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape));
@@ -272,24 +305,26 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
} else {
- E->get().rc--;
+ //E->get().rc--;
if (node)
E->get().shapes.erase(ShapePair(p_body_shape,p_local_shape));
- if (E->get().rc==0) {
+ bool in_scene = E->get().in_scene;
+
+ 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 (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 (in_scene)
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
}
contact_monitor->body_map.erase(E);
}
- if (node && E->get().in_scene) {
+ if (node && in_scene) {
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_local_shape);
}
@@ -381,6 +416,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
//process remotions
+
for(int i=0;i<toremove_count;i++) {
_body_inout(0,toremove[i].body_id,toremove[i].pair.body_shape,toremove[i].pair.local_shape);
@@ -388,6 +424,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
//process aditions
+
for(int i=0;i<toadd_count;i++) {
_body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape);
@@ -491,6 +528,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;
@@ -613,6 +686,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())
@@ -658,6 +751,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);
@@ -689,8 +791,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")));
@@ -699,6 +803,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"));
@@ -707,6 +812,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")));
@@ -731,6 +838,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;
@@ -798,7 +910,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;
@@ -831,7 +943,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;
@@ -851,7 +964,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()) {
@@ -875,11 +988,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
@@ -911,15 +1027,19 @@ 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;
normal=rest_info.normal;
collider=rest_info.collider_id;
collider_vel=rest_info.linear_velocity;
+ collider_shape=rest_info.shape;
+ collider_metadata=rest_info.metadata;
}
}
@@ -940,7 +1060,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);
@@ -980,7 +1100,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;
}
@@ -1008,6 +1128,20 @@ ObjectID KinematicBody2D::get_collider() const {
return collider;
}
+
+int KinematicBody2D::get_collider_shape() const {
+
+ ERR_FAIL_COND_V(!colliding,0);
+ return collider_shape;
+}
+
+Variant KinematicBody2D::get_collider_metadata() const {
+
+ ERR_FAIL_COND_V(!colliding,0);
+ return collider_metadata;
+
+}
+
void KinematicBody2D::set_collide_with_static_bodies(bool p_enable) {
collide_static=p_enable;
@@ -1071,6 +1205,8 @@ void KinematicBody2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody2D::get_collision_normal);
ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody2D::get_collider_velocity);
ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::_get_collider);
+ ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody2D::get_collider_shape);
+ ObjectTypeDB::bind_method(_MD("get_collider_metadata"),&KinematicBody2D::get_collider_metadata);
ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody2D::set_collide_with_static_bodies);
@@ -1107,6 +1243,8 @@ KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KI
colliding=false;
collider=0;
+ collider_shape=0;
+
margin=0.08;
}
KinematicBody2D::~KinematicBody2D() {
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 7e3fd978a0..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;
@@ -156,7 +167,7 @@ private:
};
struct BodyState {
- int rc;
+ //int rc;
bool in_scene;
VSet<ShapePair> shapes;
};
@@ -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();
@@ -254,7 +276,8 @@ class KinematicBody2D : public PhysicsBody2D {
Vector2 normal;
Vector2 collider_vel;
ObjectID collider;
-
+ int collider_shape;
+ Variant collider_metadata;
Variant _get_collider() const;
@@ -273,6 +296,8 @@ public:
Vector2 get_collision_normal() const;
Vector2 get_collider_velocity() const;
ObjectID get_collider() const;
+ int get_collider_shape() const;
+ Variant get_collider_metadata() const;
void set_collide_with_static_bodies(bool p_enable);
bool can_collide_with_static_bodies() const;
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 7d033ed87f..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 {
@@ -64,20 +65,20 @@ void Sprite::_notification(int p_what) {
break;
*/
- Size2i s;
- Rect2i src_rect;
+ Size2 s;
+ Rect2 src_rect;
if (region) {
s=region_rect.size;
src_rect=region_rect;
} else {
- s = texture->get_size();
- s=s/Size2i(hframes,vframes);
+ s = Size2(texture->get_size());
+ s=s/Size2(hframes,vframes);
src_rect.size=s;
- src_rect.pos.x+=(frame%hframes)*s.x;
- src_rect.pos.y+=(frame/hframes)*s.y;
+ src_rect.pos.x+=float(frame%hframes)*s.x;
+ src_rect.pos.y+=float(frame/hframes)*s.y;
}
@@ -85,7 +86,7 @@ void Sprite::_notification(int p_what) {
if (centered)
ofs-=s/2;
- Rect2i dst_rect(ofs,s);
+ Rect2 dst_rect(ofs,s);
if (hflip)
dst_rect.size.x=-dst_rect.size.x;
@@ -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 6403454588..9fcf34cee6 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -33,7 +33,7 @@ void TileMap::_notification(int p_what) {
switch(p_what) {
- case NOTIFICATION_ENTER_SCENE: {
+ case NOTIFICATION_ENTER_TREE: {
pending_update=true;
_update_dirty_quadrants();
@@ -43,7 +43,7 @@ void TileMap::_notification(int p_what) {
} break;
- case NOTIFICATION_EXIT_SCENE: {
+ case NOTIFICATION_EXIT_TREE: {
_update_quadrant_space(RID());
@@ -68,7 +68,7 @@ void TileMap::_update_quadrant_space(const RID& p_space) {
void TileMap::_update_quadrant_transform() {
- if (!is_inside_scene())
+ if (!is_inside_tree())
return;
Matrix32 global_transform = get_global_transform();
@@ -106,9 +106,9 @@ Ref<TileSet> TileMap::get_tileset() const {
return tile_set;
}
-void TileMap::set_cell_size(int p_size) {
+void TileMap::set_cell_size(Size2 p_size) {
- ERR_FAIL_COND(p_size<1);
+ ERR_FAIL_COND(p_size.x<1 || p_size.y<1);
_clear_quadrants();
cell_size=p_size;
@@ -117,7 +117,7 @@ void TileMap::set_cell_size(int p_size) {
}
-int TileMap::get_cell_size() const {
+Size2 TileMap::get_cell_size() const {
return cell_size;
}
@@ -164,13 +164,14 @@ void TileMap::_update_dirty_quadrants() {
if (!pending_update)
return;
- if (!is_inside_scene())
+ if (!is_inside_tree())
return;
if (!tile_set.is_valid())
return;
VisualServer *vs = VisualServer::get_singleton();
Physics2DServer *ps = Physics2DServer::get_singleton();
+ Vector2 tofs = get_cell_draw_offset();
while (dirty_quadrant_list.first()) {
@@ -178,6 +179,7 @@ void TileMap::_update_dirty_quadrants() {
vs->canvas_item_clear(q.canvas_item);
ps->body_clear_shapes(q.static_body);
+ int shape_idx=0;
for(int i=0;i<q.cells.size();i++) {
@@ -189,7 +191,7 @@ 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 = Point2( E->key().x, E->key().y )*cell_size - q.pos;
+ Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs;
if (!tex.is_valid())
continue;
@@ -258,6 +260,8 @@ void TileMap::_update_dirty_quadrants() {
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));
+
}
}
}
@@ -299,17 +303,22 @@ void TileMap::_recompute_rect_cache() {
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
- Rect2 r( Point2(E->key().x, E->key().y)*cell_size*quadrant_size, Size2(1,1)*cell_size*quadrant_size );
+ 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) );
if (E==quadrant_map.front())
r_total=r;
else
r_total=r_total.merge(r);
}
+
if (r_total==Rect2()) {
rect_cache=Rect2(-10,-10,20,20);
} else {
- rect_cache=r_total;
+ rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*quadrant_size);
}
item_rect_changed();
@@ -323,8 +332,10 @@ void TileMap::_recompute_rect_cache() {
Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) {
Matrix32 xform;
- xform.set_origin(Point2(p_qk.x,p_qk.y)*quadrant_size*cell_size);
+ //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);
+ 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 );
@@ -334,14 +345,13 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const
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()) {
+ 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_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
- q.pos=Vector2(p_qk.x,p_qk.y)*quadrant_size*cell_size;
rect_cache_dirty=true;
quadrant_order_dirty=true;
@@ -369,7 +379,7 @@ 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");
}
@@ -478,8 +488,11 @@ void TileMap::_recreate_quadrants() {
}
Q->get().cells.insert(E->key());
-
+ _make_quadrant_dirty(Q);
}
+
+
+
}
void TileMap::_clear_quadrants() {
@@ -614,6 +627,152 @@ uint32_t TileMap::get_collision_layer_mask() const {
return collision_layer;
}
+void TileMap::set_mode(Mode p_mode) {
+
+ _clear_quadrants();
+ mode=p_mode;
+ _recreate_quadrants();
+ emit_signal("settings_changed");
+}
+
+TileMap::Mode TileMap::get_mode() const {
+ return mode;
+}
+
+void TileMap::set_half_offset(HalfOffset p_half_offset) {
+
+ _clear_quadrants();
+ half_offset=p_half_offset;
+ _recreate_quadrants();
+ emit_signal("settings_changed");
+}
+
+Vector2 TileMap::get_cell_draw_offset() const {
+
+ switch(mode) {
+
+ case MODE_SQUARE: {
+
+ return Vector2();
+ } break;
+ case MODE_ISOMETRIC: {
+
+ return Vector2(-cell_size.x*0.5,0);
+
+ } break;
+ case MODE_CUSTOM: {
+
+ Vector2 min;
+ min.x = MIN(custom_transform[0].x,min.x);
+ min.y = MIN(custom_transform[0].y,min.y);
+ min.x = MIN(custom_transform[1].x,min.x);
+ min.y = MIN(custom_transform[1].y,min.y);
+ return min;
+ } break;
+ }
+
+ return Vector2();
+
+}
+
+TileMap::HalfOffset TileMap::get_half_offset() const {
+ return half_offset;
+}
+
+Matrix32 TileMap::get_cell_transform() const {
+
+ switch(mode) {
+
+ case MODE_SQUARE: {
+
+ Matrix32 m;
+ m[0]*=cell_size.x;
+ m[1]*=cell_size.y;
+ return m;
+ } break;
+ case MODE_ISOMETRIC: {
+
+ //isometric only makes sense when y is positive in both x and y vectors, otherwise
+ //the drawing of tiles will overlap
+ Matrix32 m;
+ m[0]=Vector2(cell_size.x*0.5,cell_size.y*0.5);
+ m[1]=Vector2(-cell_size.x*0.5,cell_size.y*0.5);
+ return m;
+
+ } break;
+ case MODE_CUSTOM: {
+
+ return custom_transform;
+ } break;
+ }
+
+ return Matrix32();
+}
+
+void TileMap::set_custom_transform(const Matrix32& p_xform) {
+
+ _clear_quadrants();
+ custom_transform=p_xform;
+ _recreate_quadrants();
+ emit_signal("settings_changed");
+
+}
+
+Matrix32 TileMap::get_custom_transform() const{
+
+ return custom_transform;
+}
+
+Vector2 TileMap::_map_to_world(int x,int y,bool p_ignore_ofs) const {
+
+ Vector2 ret = get_cell_transform().xform(Vector2(x,y));
+ if (!p_ignore_ofs) {
+ switch(half_offset) {
+
+ case HALF_OFFSET_X: {
+ if (ABS(y)&1) {
+
+ ret+=get_cell_transform()[0]*0.5;
+ }
+ } break;
+ case HALF_OFFSET_Y: {
+ if (ABS(x)&1) {
+ ret+=get_cell_transform()[1]*0.5;
+ }
+ } break;
+ default: {}
+ }
+ }
+ return ret;
+}
+Vector2 TileMap::map_to_world(const Vector2& p_pos,bool p_ignore_ofs) const {
+
+ return _map_to_world(p_pos.x,p_pos.y,p_ignore_ofs);
+}
+Vector2 TileMap::world_to_map(const Vector2& p_pos) const{
+
+ Vector2 ret = get_cell_transform().affine_inverse().xform(p_pos);
+
+
+ switch(half_offset) {
+
+ case HALF_OFFSET_X: {
+ if (int(ret.y)&1) {
+
+ ret.x-=0.5;
+ }
+ } break;
+ case HALF_OFFSET_Y: {
+ if (int(ret.x)&1) {
+ ret.y-=0.5;
+ }
+ } break;
+ default: {}
+ }
+
+ return ret.floor();
+}
+
void TileMap::_bind_methods() {
@@ -621,10 +780,21 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
ObjectTypeDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_tileset);
+ ObjectTypeDB::bind_method(_MD("set_mode","mode"),&TileMap::set_mode);
+ ObjectTypeDB::bind_method(_MD("get_mode"),&TileMap::get_mode);
+
+ ObjectTypeDB::bind_method(_MD("set_half_offset","half_offset"),&TileMap::set_half_offset);
+ ObjectTypeDB::bind_method(_MD("get_half_offset"),&TileMap::get_half_offset);
+
+ ObjectTypeDB::bind_method(_MD("set_custom_transform","custom_transform"),&TileMap::set_custom_transform);
+ ObjectTypeDB::bind_method(_MD("get_custom_transform"),&TileMap::get_custom_transform);
ObjectTypeDB::bind_method(_MD("set_cell_size","size"),&TileMap::set_cell_size);
ObjectTypeDB::bind_method(_MD("get_cell_size"),&TileMap::get_cell_size);
+ ObjectTypeDB::bind_method(_MD("_set_old_cell_size","size"),&TileMap::_set_old_cell_size);
+ ObjectTypeDB::bind_method(_MD("_get_old_cell_size"),&TileMap::_get_old_cell_size);
+
ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size);
@@ -650,6 +820,9 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("clear"),&TileMap::clear);
+ ObjectTypeDB::bind_method(_MD("map_to_world","mappos","ignore_half_ofs"),&TileMap::map_to_world,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("world_to_map","worldpos"),&TileMap::world_to_map);
+
ObjectTypeDB::bind_method(_MD("_clear_quadrants"),&TileMap::_clear_quadrants);
ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
ObjectTypeDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants);
@@ -657,17 +830,28 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_tile_data"),&TileMap::_set_tile_data);
ObjectTypeDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_tile_data);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),_SCS("set_mode"),_SCS("get_mode"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1",0),_SCS("_set_old_cell_size"),_SCS("_get_old_cell_size"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"cell/size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
+ 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::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"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
ADD_SIGNAL(MethodInfo("settings_changed"));
BIND_CONSTANT( INVALID_CELL );
+ BIND_CONSTANT( MODE_SQUARE );
+ BIND_CONSTANT( MODE_ISOMETRIC );
+ BIND_CONSTANT( MODE_CUSTOM );
+ BIND_CONSTANT( HALF_OFFSET_X );
+ BIND_CONSTANT( HALF_OFFSET_Y );
+ BIND_CONSTANT( HALF_OFFSET_DISABLED );
+
}
TileMap::TileMap() {
@@ -678,12 +862,14 @@ TileMap::TileMap() {
pending_update=false;
quadrant_order_dirty=false;
quadrant_size=16;
- cell_size=64;
+ cell_size=Size2(64,64);
center_x=false;
center_y=false;
collision_layer=1;
friction=1;
bounce=0;
+ mode=MODE_SQUARE;
+ half_offset=HALF_OFFSET_DISABLED;
fp_adjust=0.01;
fp_adjust=0.01;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index d21437e30f..4e9e2e7e97 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -37,12 +37,30 @@
class TileMap : public Node2D {
OBJ_TYPE( TileMap, Node2D );
+public:
+
+ enum Mode {
+ MODE_SQUARE,
+ MODE_ISOMETRIC,
+ MODE_CUSTOM
+ };
+
+ enum HalfOffset {
+ HALF_OFFSET_X,
+ HALF_OFFSET_Y,
+ HALF_OFFSET_DISABLED,
+ };
+private:
Ref<TileSet> tile_set;
- int cell_size;
+ Size2i cell_size;
int quadrant_size;
bool center_x,center_y;
+ Mode mode;
+ Matrix32 custom_transform;
+ HalfOffset half_offset;
+
union PosKey {
@@ -117,6 +135,12 @@ class TileMap : public Node2D {
void _set_tile_data(const DVector<int>& p_data);
DVector<int> _get_tile_data() const;
+
+ void _set_old_cell_size(int p_size) { set_cell_size(Size2(p_size,p_size)); }
+ int _get_old_cell_size() const { return cell_size.x; }
+
+ _FORCE_INLINE_ Vector2 _map_to_world(int p_x,int p_y,bool p_ignore_ofs=false) const;
+
protected:
@@ -132,8 +156,8 @@ public:
void set_tileset(const Ref<TileSet>& p_tileset);
Ref<TileSet> get_tileset() const;
- void set_cell_size(int p_size);
- int get_cell_size() const;
+ void set_cell_size(Size2 p_size);
+ Size2 get_cell_size() const;
void set_quadrant_size(int p_size);
int get_quadrant_size() const;
@@ -159,10 +183,28 @@ public:
void set_collision_bounce(float p_bounce);
float get_collision_bounce() const;
+ void set_mode(Mode p_mode);
+ Mode get_mode() const;
+
+ void set_half_offset(HalfOffset p_half_offset);
+ HalfOffset get_half_offset() const;
+
+ void set_custom_transform(const Matrix32& p_xform);
+ Matrix32 get_custom_transform() const;
+
+ Matrix32 get_cell_transform() const;
+ Vector2 get_cell_draw_offset() const;
+
+ Vector2 map_to_world(const Vector2& p_pos, bool p_ignore_ofs=false) const;
+ Vector2 world_to_map(const Vector2& p_pos) const;
+
void clear();
TileMap();
~TileMap();
};
+VARIANT_ENUM_CAST(TileMap::Mode);
+VARIANT_ENUM_CAST(TileMap::HalfOffset);
+
#endif // TILE_MAP_H
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index e5eb193f6f..22534eeb0e 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -64,7 +64,7 @@ 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));
_change_notify("rect");
@@ -85,7 +85,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 +97,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;
@@ -190,7 +190,7 @@ void VisibilityEnabler2D::_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);
}
@@ -207,9 +207,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 +222,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 +235,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();
diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp
new file mode 100644
index 0000000000..d441abfaf1
--- /dev/null
+++ b/scene/2d/y_sort.cpp
@@ -0,0 +1,29 @@
+#include "y_sort.h"
+
+
+
+void YSort::set_sort_enabled(bool p_enabled) {
+
+ sort_enabled=p_enabled;
+ VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),sort_enabled);
+}
+
+bool YSort::is_sort_enabled() const {
+
+ return sort_enabled;
+}
+
+void YSort::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_sort_enabled","enabled"),&YSort::set_sort_enabled);
+ ObjectTypeDB::bind_method(_MD("is_sort_enabled"),&YSort::is_sort_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"sort/enabled"),_SCS("set_sort_enabled"),_SCS("is_sort_enabled"));
+}
+
+
+YSort::YSort() {
+
+ sort_enabled=true;
+ VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),true);
+}
diff --git a/scene/2d/y_sort.h b/scene/2d/y_sort.h
new file mode 100644
index 0000000000..6d04a67e42
--- /dev/null
+++ b/scene/2d/y_sort.h
@@ -0,0 +1,17 @@
+#ifndef Y_SORT_H
+#define Y_SORT_H
+
+#include "scene/2d/node_2d.h"
+
+class YSort : public Node2D {
+ OBJ_TYPE(YSort,Node2D);
+ bool sort_enabled;
+ static void _bind_methods();
+public:
+
+ void set_sort_enabled(bool p_enabled);
+ bool is_sort_enabled() const;
+ YSort();
+};
+
+#endif // Y_SORT_H
diff --git a/scene/3d/SCsub b/scene/3d/SCsub
index 6789851aab..3c2144bedc 100644
--- a/scene/3d/SCsub
+++ b/scene/3d/SCsub
@@ -1,7 +1,6 @@
Import('env')
-print("V: "+env["disable_3d"])
if (env["disable_3d"]=="yes"):
env.scene_sources.append("3d/spatial.cpp")
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index f5895453cc..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,21 +272,29 @@ bool Area::is_monitoring_enabled() const {
}
-void Area::set_ray_pickable(bool p_ray_pickable) {
+Array Area::get_overlapping_bodies() const {
- ray_pickable=p_ray_pickable;
- PhysicsServer::get_singleton()->area_set_ray_pickable(get_rid(),p_ray_pickable);
-}
+ 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;
+ }
-bool Area::is_ray_pickable() const {
+ }
- return ray_pickable;
+ 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);
@@ -289,12 +314,12 @@ void Area::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority);
ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority);
- ObjectTypeDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&Area::set_ray_pickable);
- ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&Area::is_ray_pickable);
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);
@@ -310,7 +335,6 @@ void Area::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable"));
}
@@ -318,12 +342,13 @@ 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;
priority=0;
monitoring=false;
- ray_pickable=false;
+ set_ray_pickable(false);
set_enable_monitoring(true);
}
diff --git a/scene/3d/area.h b/scene/3d/area.h
index 92b5d39f59..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 ray_pickable;
+ 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;
};
@@ -109,12 +110,11 @@ public:
void set_priority(real_t p_priority);
real_t get_priority() const;
- void set_ray_pickable(bool p_ray_pickable);
- bool is_ray_pickable() const;
-
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 4245bfa2c9..27420f8002 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
@@ -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();
}
@@ -219,11 +231,14 @@ void Camera::_notification(int p_what) {
}
+ camera_group = "_vp_cameras"+itos(get_viewport()->get_instance_ID());
+ add_to_group(camera_group);
if (viewport_ptr)
viewport_ptr->cameras.insert(this);
if (current)
make_current();
+
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -241,6 +256,8 @@ void Camera::_notification(int p_what) {
if (viewport_ptr)
viewport_ptr->cameras.erase(this);
viewport_ptr=NULL;
+ remove_from_group(camera_group);
+
} break;
case NOTIFICATION_BECAME_CURRENT: {
@@ -262,7 +279,7 @@ void Camera::_notification(int p_what) {
Transform Camera::get_camera_transform() const {
- return get_global_transform();
+ return get_global_transform().orthonormalized();
}
void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -304,7 +321,7 @@ void Camera::make_current() {
current=true;
- if (!is_inside_scene())
+ if (!is_inside_tree())
return;
if (viewport_ptr) {
@@ -314,22 +331,40 @@ void Camera::make_current() {
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this);
}
+
+void Camera::_camera_make_next_current(Node *p_exclude) {
+
+ if (this==p_exclude)
+ return;
+ if (!is_inside_tree())
+ return;
+ if (get_viewport()->get_camera()!=NULL)
+ return;
+
+ make_current();
+}
+
+
void Camera::clear_current() {
current=false;
- if (!is_inside_scene())
+ if (!is_inside_tree())
return;
if (viewport_ptr) {
- if (viewport_ptr->get_camera()==this)
+ 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_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this);
+
+ }
}
}
bool Camera::is_current() const {
- if (is_inside_scene()) {
+ if (is_inside_tree()) {
if (viewport_ptr)
return viewport_ptr->get_camera()==this;
} else
@@ -439,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;
@@ -456,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;
@@ -482,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();
@@ -493,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;
@@ -504,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;
@@ -535,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;
@@ -636,6 +686,7 @@ void Camera::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment);
ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode);
ObjectTypeDB::bind_method(_MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode);
+ ObjectTypeDB::bind_method(_MD("_camera_make_next_current"),&Camera::_camera_make_next_current);
//ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current );
BIND_CONSTANT( PROJECTION_PERSPECTIVE );
@@ -695,7 +746,7 @@ Vector<Plane> Camera::get_frustum() const {
else
cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH);
- return cm.get_projection_planes(get_global_transform());
+ return cm.get_projection_planes(get_camera_transform());
}
@@ -704,7 +755,7 @@ Vector<Plane> Camera::get_frustum() const {
void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) {
Transform lookat;
- lookat.origin=get_global_transform().origin;
+ lookat.origin=get_camera_transform().origin;
lookat=lookat.looking_at(p_target,p_up_normal);
set_global_transform(lookat);
}
@@ -718,6 +769,27 @@ void Camera::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, cons
}
+void Camera::set_v_offset(float p_offset) {
+
+ v_offset=p_offset;
+ _update_camera();;
+}
+
+float Camera::get_v_offset() const {
+
+ return v_offset;
+}
+
+void Camera::set_h_offset(float p_offset) {
+ h_offset=p_offset;
+ _update_camera();
+}
+
+float Camera::get_h_offset() const {
+
+ return h_offset;
+}
+
Camera::Camera() {
@@ -732,7 +804,10 @@ Camera::Camera() {
mode=PROJECTION_PERSPECTIVE;
set_perspective(60.0,0.1,100.0);
keep_aspect=KEEP_HEIGHT;
- layers=0xFFFFFFFF;
+ 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 014c7cb520..950688dfda 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -61,11 +61,15 @@ private:
float fov;
float size;
float near,far;
+ float v_offset;
+ float h_offset;
KeepAspect keep_aspect;
RID camera;
RID scenario_id;
+ String camera_group;
+
uint32_t layers;
Viewport *viewport_ptr;
@@ -74,6 +78,7 @@ private:
virtual bool _can_gizmo_scale() const;
virtual RES _get_gizmo_geometry() const;
+ void _camera_make_next_current(Node *p_exclude);
//void _camera_make_current(Node *p_camera);
@@ -137,6 +142,12 @@ public:
void look_at(const Vector3& p_target, const Vector3& p_up_normal);
void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal);
+ void set_v_offset(float p_offset);
+ float get_v_offset() const;
+
+ void set_h_offset(float p_offset);
+ float get_h_offset() const;
+
Camera();
~Camera();
diff --git a/scene/3d/car_body.cpp b/scene/3d/car_body.cpp
deleted file mode 100644
index a21598b07c..0000000000
--- a/scene/3d/car_body.cpp
+++ /dev/null
@@ -1,741 +0,0 @@
-/*************************************************************************/
-/* car_body.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 "car_body.h"
-
-#define DEG2RADMUL (Math_PI/180.0)
-#define RAD2DEGMUL (180.0/Math_PI)
-
-void CarWheel::_notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_ENTER_SCENE) {
-
- if (!get_parent())
- return;
- CarBody *cb = get_parent()->cast_to<CarBody>();
- if (!cb)
- return;
- body=cb;
- local_xform=get_transform();
- cb->wheels.push_back(this);
- }
- if (p_what==NOTIFICATION_EXIT_SCENE) {
-
- if (!get_parent())
- return;
- CarBody *cb = get_parent()->cast_to<CarBody>();
- if (!cb)
- return;
- cb->wheels.erase(this);
- body=NULL;
- }
-}
-
-void CarWheel::set_side_friction(real_t p_friction) {
-
- side_friction=p_friction;
-}
-void CarWheel::set_forward_friction(real_t p_friction) {
-
- forward_friction=p_friction;
-}
-void CarWheel::set_travel(real_t p_travel) {
-
- travel=p_travel;
- update_gizmo();
-
-}
-void CarWheel::set_radius(real_t p_radius) {
-
- radius=p_radius;
- update_gizmo();
-
-}
-void CarWheel::set_resting_frac(real_t p_frac) {
-
- resting_frac=p_frac;
-}
-void CarWheel::set_damping_frac(real_t p_frac) {
-
- damping_frac=p_frac;
-}
-void CarWheel::set_num_rays(real_t p_rays) {
-
- num_rays=p_rays;
-}
-
-real_t CarWheel::get_side_friction() const{
-
- return side_friction;
-}
-real_t CarWheel::get_forward_friction() const{
-
- return forward_friction;
-}
-real_t CarWheel::get_travel() const{
-
- return travel;
-}
-real_t CarWheel::get_radius() const{
-
- return radius;
-}
-real_t CarWheel::get_resting_frac() const{
-
- return resting_frac;
-}
-real_t CarWheel::get_damping_frac() const{
-
- return damping_frac;
-}
-
-int CarWheel::get_num_rays() const{
-
- return num_rays;
-}
-
-
-void CarWheel::update(real_t dt) {
-
-
- if (dt <= 0.0f)
- return;
-
- float origAngVel = angVel;
-
- if (locked)
- {
- angVel = 0;
- torque = 0;
- }
- else
- {
-
- float wheelMass = 0.03f * body->mass;
- float inertia = 0.5f * (radius * radius) * wheelMass;
-
- angVel += torque * dt / inertia;
- torque = 0;
-
- // prevent friction from reversing dir - todo do this better
- // by limiting the torque
- if (((origAngVel > angVelForGrip) && (angVel < angVelForGrip)) ||
- ((origAngVel < angVelForGrip) && (angVel > angVelForGrip)))
- angVel = angVelForGrip;
-
- angVel += driveTorque * dt / inertia;
- driveTorque = 0;
-
- float maxAngVel = 200;
- print_line("angvel: "+rtos(angVel));
- angVel = CLAMP(angVel, -maxAngVel, maxAngVel);
-
- axisAngle += Math::rad2deg(dt * angVel);
- }
-}
-
-bool CarWheel::add_forces(PhysicsDirectBodyState *s) {
-
-
- Vector3 force;
-
- PhysicsDirectSpaceState *space = s->get_space_state();
-
- Transform world = s->get_transform() * local_xform;
-
- // OpenGl has differnet row/column order for matrixes than XNA has ..
- //Vector3 wheelFwd = world.get_basis().get_axis(Vector3::AXIS_Z);
- //Vector3 wheelFwd = RotationMatrix(mSteerAngle, worldAxis) * carBody.GetOrientation().GetCol(0);
- Vector3 wheelUp = world.get_basis().get_axis(Vector3::AXIS_Y);
- Vector3 wheelFwd = Matrix3(wheelUp,Math::deg2rad(steerAngle)).xform( world.get_basis().get_axis(Vector3::AXIS_Z) );
- Vector3 wheelLeft = -wheelUp.cross(wheelFwd).normalized();
- Vector3 worldPos = world.origin;
- Vector3 worldAxis = wheelUp;
-
- // start of ray
- float rayLen = 2.0f * radius + travel;
- Vector3 wheelRayEnd = worldPos - radius * worldAxis;
- Vector3 wheelRayBegin = wheelRayEnd + rayLen * worldAxis;
- //wheelRayEnd = -rayLen * worldAxis;
-
- //Assert(PhysicsSystem.CurrentPhysicsSystem);
-
-
- ///Assert(collSystem);
- ///
- const int maxNumRays = 32;
-
- int numRaysUse = MIN(num_rays, maxNumRays);
-
- // adjust the start position of the ray - divide the wheel into numRays+2
- // rays, but don't use the first/last.
- float deltaFwd = (2.0f * radius) / (numRaysUse + 1);
- float deltaFwdStart = deltaFwd;
-
- float fracs[maxNumRays];
- Vector3 segmentEnds[maxNumRays];
- Vector3 groundPositions[maxNumRays];
- Vector3 groundNormals[maxNumRays];
-
-
- lastOnFloor = false;
- int bestIRay = 0;
- int iRay;
-
-
- for (iRay = 0; iRay < numRaysUse; ++iRay)
- {
- fracs[iRay] = 1e20;
- // work out the offset relative to the middle ray
- float distFwd = (deltaFwdStart + iRay * deltaFwd) - radius;
- float zOffset = radius * (1.0f - (float)Math::cos( Math::deg2rad( 90.0f * (distFwd / radius))));
-
- segmentEnds[iRay] = wheelRayEnd + distFwd * wheelFwd + zOffset * wheelUp;
-
-
- PhysicsDirectSpaceState::RayResult rr;
-
- bool collided = space->intersect_ray(wheelRayBegin,segmentEnds[iRay],rr,body->exclude);
-
-
- if (collided){
- lastOnFloor = true;
- groundPositions[iRay]=rr.position;
- groundNormals[iRay]=rr.normal;
- fracs[iRay] = ((wheelRayBegin-rr.position).length() / (wheelRayBegin-wheelRayEnd).length());
- if (fracs[iRay] < fracs[bestIRay])
- bestIRay = iRay;
- }
- }
-
-
- if (!lastOnFloor)
- return false;
-
- //Assert(bestIRay < numRays);
-
- // use the best one
- Vector3 groundPos = groundPositions[bestIRay];
- float frac = fracs[bestIRay];
-
- // const Vector3 groundNormal = (worldPos - segments[bestIRay].GetEnd()).NormaliseSafe();
- // const Vector3 groundNormal = groundNormals[bestIRay];
-
-
- Vector3 groundNormal = worldAxis;
-
- if (numRaysUse > 1)
- {
- for (iRay = 0; iRay < numRaysUse; ++iRay)
- {
- if (fracs[iRay] <= 1.0f)
- {
- groundNormal += (1.0f - fracs[iRay]) * (worldPos - segmentEnds[iRay]);
- }
- }
-
- groundNormal.normalize();
-
- }
- else
- {
- groundNormal = groundNormals[bestIRay];
- }
-
-
-
- float spring = (body->mass/body->wheels.size()) * s->get_total_gravity().length() / (resting_frac * travel);
-
- float displacement = rayLen * (1.0f - frac);
- displacement = CLAMP(displacement, 0, travel);
-
-
-
- float displacementForceMag = displacement * spring;
-
- // reduce force when suspension is par to ground
- displacementForceMag *= groundNormals[bestIRay].dot(worldAxis);
-
- // apply damping
- float damping = 2.0f * (float)Math::sqrt(spring * body->mass);
- damping /= body->wheels.size(); // assume wheels act together
- damping *= damping_frac; // a bit bouncy
-
- float upSpeed = (displacement - lastDisplacement) / s->get_step();
-
- float dampingForceMag = upSpeed * damping;
-
- float totalForceMag = displacementForceMag + dampingForceMag;
-
- if (totalForceMag < 0.0f) totalForceMag = 0.0f;
-
- Vector3 extraForce = totalForceMag * worldAxis;
-
-
- force += extraForce;
- // side-slip friction and drive force. Work out wheel- and floor-relative coordinate frame
- Vector3 groundUp = groundNormal;
- Vector3 groundLeft = groundNormal.cross(wheelFwd).normalized();
-
- Vector3 groundFwd = groundLeft.cross(groundUp);
-
- Vector3 wheelPointVel = s->get_linear_velocity() +
- (s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin));// * mPos);
-
- Vector3 rimVel = -angVel * wheelLeft.cross(groundPos - worldPos);
- wheelPointVel += rimVel;
-
- // if sitting on another body then adjust for its velocity.
- /*if (worldBody != null)
- {
- Vector3 worldVel = worldBody.Velocity +
- Vector3.Cross(worldBody.AngularVelocity, groundPos - worldBody.Position);
-
- wheelPointVel -= worldVel;
- }*/
-
- // sideways forces
- float noslipVel = 0.2f;
- float slipVel = 0.4f;
- float slipFactor = 0.7f;
-
- float smallVel = 3;
- float friction = side_friction;
-
- float sideVel = wheelPointVel.dot(groundLeft);
-
- if ((sideVel > slipVel) || (sideVel < -slipVel))
- friction *= slipFactor;
- else
- if ((sideVel > noslipVel) || (sideVel < -noslipVel))
- friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(sideVel) - noslipVel) / (slipVel - noslipVel);
-
- if (sideVel < 0.0f)
- friction *= -1.0f;
-
- if (Math::absf(sideVel) < smallVel)
- friction *= Math::absf(sideVel) / smallVel;
-
- float sideForce = -friction * totalForceMag;
-
- extraForce = sideForce * groundLeft;
- force += extraForce;
- // fwd/back forces
- friction = forward_friction;
- float fwdVel = wheelPointVel.dot(groundFwd);
-
- if ((fwdVel > slipVel) || (fwdVel < -slipVel))
- friction *= slipFactor;
- else
- if ((fwdVel > noslipVel) || (fwdVel < -noslipVel))
- friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(fwdVel) - noslipVel) / (slipVel - noslipVel);
-
- if (fwdVel < 0.0f)
- friction *= -1.0f;
-
- if (Math::absf(fwdVel) < smallVel)
- friction *= Math::absf(fwdVel) / smallVel;
-
- float fwdForce = -friction * totalForceMag;
-
- extraForce = fwdForce * groundFwd;
- force += extraForce;
-
-
- //if (!force.IsSensible())
- //{
- // TRACE_FILE_IF(ONCE_1)
- // TRACE("Bad force in car wheel\n");
- // return true;
- //}
-
- // fwd force also spins the wheel
- Vector3 wheelCentreVel = s->get_linear_velocity() +
- (s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin));
-
- angVelForGrip = wheelCentreVel.dot(groundFwd) / radius;
- torque += -fwdForce * radius;
-
- // add force to car
-// carBody.AddWorldForce(force, groundPos);
-
- s->add_force(force,(groundPos-s->get_transform().origin));
-
- // add force to the world
- /*
- if (worldBody != null && !worldBody.Immovable)
- {
- // todo get the position in the right place...
- // also limit the velocity that this force can produce by looking at the
- // mass/inertia of the other object
- float maxOtherBodyAcc = 500.0f;
- float maxOtherBodyForce = maxOtherBodyAcc * worldBody.Mass;
-
- if (force.LengthSquared() > (maxOtherBodyForce * maxOtherBodyForce))
- force *= maxOtherBodyForce / force.Length();
-
- worldBody.AddWorldForce(-force, groundPos);
- }*/
-
- Transform wheel_xf = local_xform;
- wheel_xf.origin += wheelUp * displacement;
- wheel_xf.basis = wheel_xf.basis * Matrix3(Vector3(0,1,0),Math::deg2rad(steerAngle));
- //wheel_xf.basis = wheel_xf.basis * Matrix3(wheel_xf.basis[0],-Math::deg2rad(axisAngle));
-
- set_transform(wheel_xf);
- lastDisplacement=displacement;
- return true;
-
-}
-
-void CarWheel::set_type_drive(bool p_enable) {
-
- type_drive=p_enable;
-}
-
-bool CarWheel::is_type_drive() const {
-
- return type_drive;
-}
-
-void CarWheel::set_type_steer(bool p_enable) {
-
- type_steer=p_enable;
-}
-
-bool CarWheel::is_type_steer() const {
-
- return type_steer;
-}
-
-
-void CarWheel::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("set_side_friction","friction"),&CarWheel::set_side_friction);
- ObjectTypeDB::bind_method(_MD("set_forward_friction","friction"),&CarWheel::set_forward_friction);
- ObjectTypeDB::bind_method(_MD("set_travel","distance"),&CarWheel::set_travel);
- ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CarWheel::set_radius);
- ObjectTypeDB::bind_method(_MD("set_resting_frac","frac"),&CarWheel::set_resting_frac);
- ObjectTypeDB::bind_method(_MD("set_damping_frac","frac"),&CarWheel::set_damping_frac);
- ObjectTypeDB::bind_method(_MD("set_num_rays","amount"),&CarWheel::set_num_rays);
-
- ObjectTypeDB::bind_method(_MD("get_side_friction"),&CarWheel::get_side_friction);
- ObjectTypeDB::bind_method(_MD("get_forward_friction"),&CarWheel::get_forward_friction);
- ObjectTypeDB::bind_method(_MD("get_travel"),&CarWheel::get_travel);
- ObjectTypeDB::bind_method(_MD("get_radius"),&CarWheel::get_radius);
- ObjectTypeDB::bind_method(_MD("get_resting_frac"),&CarWheel::get_resting_frac);
- ObjectTypeDB::bind_method(_MD("get_damping_frac"),&CarWheel::get_damping_frac);
- ObjectTypeDB::bind_method(_MD("get_num_rays"),&CarWheel::get_num_rays);
-
- ObjectTypeDB::bind_method(_MD("set_type_drive","enable"),&CarWheel::set_type_drive);
- ObjectTypeDB::bind_method(_MD("is_type_drive"),&CarWheel::is_type_drive);
-
- ObjectTypeDB::bind_method(_MD("set_type_steer","enable"),&CarWheel::set_type_steer);
- ObjectTypeDB::bind_method(_MD("is_type_steer"),&CarWheel::is_type_steer);
-
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/drive"),_SCS("set_type_drive"),_SCS("is_type_drive"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/steer"),_SCS("set_type_steer"),_SCS("is_type_steer"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/side_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_side_friction"),_SCS("get_side_friction"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/forward_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_forward_friction"),_SCS("get_forward_friction"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/travel",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_travel"),_SCS("get_travel"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_radius"),_SCS("get_radius"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/resting_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_resting_frac"),_SCS("get_resting_frac"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/damping_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_damping_frac"),_SCS("get_damping_frac"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/num_rays",PROPERTY_HINT_RANGE,"1,32,1"),_SCS("set_num_rays"),_SCS("get_num_rays"));
-
-}
-
-CarWheel::CarWheel() {
-
- side_friction=4.7;
- forward_friction=5.0;
- travel=0.2;
- radius=0.4;
- resting_frac=0.45;
- damping_frac=0.3;
- num_rays=1;
-
- angVel = 0.0f;
- steerAngle = 0.0f;
- torque = 0.0f;
- driveTorque = 0.0f;
- axisAngle = 0.0f;
- upSpeed = 0.0f;
- locked = false;
- lastDisplacement = 0.0f;
- lastOnFloor = false;
- angVelForGrip = 0.0f;
- angVelForGrip=0;
-
- type_drive=false;
- type_steer=false;
-
-}
-
-///
-
-
-void CarBody::set_max_steer_angle(real_t p_angle) {
-
- max_steer_angle=p_angle;
-}
-void CarBody::set_steer_rate(real_t p_rate) {
-
- steer_rate=p_rate;
-}
-void CarBody::set_drive_torque(real_t p_torque) {
-
- drive_torque=p_torque;
-}
-
-real_t CarBody::get_max_steer_angle() const{
-
- return max_steer_angle;
-}
-real_t CarBody::get_steer_rate() const{
-
- return steer_rate;
-}
-real_t CarBody::get_drive_torque() const{
-
- return drive_torque;
-}
-
-
-void CarBody::set_target_steering(float p_steering) {
-
- target_steering=p_steering;
-}
-
-void CarBody::set_target_accelerate(float p_accelerate) {
- target_accelerate=p_accelerate;
-}
-
-void CarBody::set_hand_brake(float p_amont) {
-
- hand_brake=p_amont;
-}
-
-real_t CarBody::get_target_steering() const {
-
- return target_steering;
-}
-real_t CarBody::get_target_accelerate() const {
-
- return target_accelerate;
-}
-real_t CarBody::get_hand_brake() const {
-
- return hand_brake;
-}
-
-
-void CarBody::_direct_state_changed(Object *p_state) {
-
- PhysicsDirectBodyState *state=p_state->cast_to<PhysicsDirectBodyState>();
-
- float dt = state->get_step();
- AABB aabb;
- int drive_total=0;
- for(int i=0;i<wheels.size();i++) {
- CarWheel *w=wheels[i];
- if (i==0) {
- aabb.pos=w->local_xform.origin;
- } else {
- aabb.expand_to(w->local_xform.origin);
- }
- if (w->type_drive)
- drive_total++;
-
- }
- // control inputs
- float deltaAccelerate = dt * 4.0f;
-
- float dAccelerate = target_accelerate - accelerate;
- dAccelerate = CLAMP(dAccelerate, -deltaAccelerate, deltaAccelerate);
- accelerate += dAccelerate;
-
- float deltaSteering = dt * steer_rate;
- float dSteering = target_steering - steering;
- dSteering = CLAMP(dSteering, -deltaSteering, deltaSteering);
- steering += dSteering;
-
- // apply these inputs
- float maxTorque = drive_torque;
-
- float torque_div = drive_total/2;
- if (torque_div>0)
- maxTorque/=torque_div;
-
-
- float alpha = ABS(max_steer_angle * steering);
- float angleSgn = steering > 0.0f ? 1.0f : -1.0f;
-
- int wheels_on_floor=0;
-
- for(int i=0;i<wheels.size();i++) {
-
- CarWheel *w=wheels[i];
- if (w->type_drive)
- w->driveTorque+=maxTorque * accelerate;
- w->locked = !w->type_steer && (hand_brake > 0.5f);
-
- if (w->type_steer) {
- //steering
-
- bool inner = (steering > 0 && w->local_xform.origin.x > 0) || (steering < 0 && w->local_xform.origin.x < 0);
-
- if (inner || alpha==0.0) {
-
- w->steerAngle = (angleSgn * alpha);
- } else {
- float dx = aabb.size.z;
- float dy = aabb.size.x;
-
- float beta = Math::atan2(dy, dx + (dy / (float)Math::tan(Math::deg2rad(alpha))));
- beta = Math::rad2deg(beta);
- w->steerAngle = (angleSgn * beta);
-
- }
- }
-
- if (w->add_forces(state))
- wheels_on_floor++;
- w->update(dt);
-
-
- }
-
- print_line("onfloor: "+itos(wheels_on_floor));
-
-
- set_ignore_transform_notification(true);
- set_global_transform(state->get_transform());
- linear_velocity=state->get_linear_velocity();
- angular_velocity=state->get_angular_velocity();
- //active=!state->is_sleeping();
- //if (get_script_instance())
- // get_script_instance()->call("_integrate_forces",state);
- set_ignore_transform_notification(false);
-
-
-}
-
-void CarBody::set_mass(real_t p_mass) {
-
- mass=p_mass;
- PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_MASS,mass);
-}
-
-real_t CarBody::get_mass() const{
-
- return mass;
-}
-
-
-void CarBody::set_friction(real_t p_friction) {
-
- friction=p_friction;
- PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction);
-}
-
-real_t CarBody::get_friction() const{
-
- return friction;
-}
-
-
-void CarBody::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("set_max_steer_angle","value"),&CarBody::set_max_steer_angle);
- ObjectTypeDB::bind_method(_MD("set_steer_rate","rate"),&CarBody::set_steer_rate);
- ObjectTypeDB::bind_method(_MD("set_drive_torque","value"),&CarBody::set_drive_torque);
-
- ObjectTypeDB::bind_method(_MD("get_max_steer_angle"),&CarBody::get_max_steer_angle);
- ObjectTypeDB::bind_method(_MD("get_steer_rate"),&CarBody::get_steer_rate);
- ObjectTypeDB::bind_method(_MD("get_drive_torque"),&CarBody::get_drive_torque);
-
- ObjectTypeDB::bind_method(_MD("set_target_steering","amount"),&CarBody::set_target_steering);
- ObjectTypeDB::bind_method(_MD("set_target_accelerate","amount"),&CarBody::set_target_accelerate);
- ObjectTypeDB::bind_method(_MD("set_hand_brake","amount"),&CarBody::set_hand_brake);
-
- ObjectTypeDB::bind_method(_MD("get_target_steering"),&CarBody::get_target_steering);
- ObjectTypeDB::bind_method(_MD("get_target_accelerate"),&CarBody::get_target_accelerate);
- ObjectTypeDB::bind_method(_MD("get_hand_brake"),&CarBody::get_hand_brake);
-
- ObjectTypeDB::bind_method(_MD("set_mass","mass"),&CarBody::set_mass);
- ObjectTypeDB::bind_method(_MD("get_mass"),&CarBody::get_mass);
-
- ObjectTypeDB::bind_method(_MD("set_friction","friction"),&CarBody::set_friction);
- ObjectTypeDB::bind_method(_MD("get_friction"),&CarBody::get_friction);
-
- ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&CarBody::_direct_state_changed);
-
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
-
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/max_steer_angle",PROPERTY_HINT_RANGE,"1,90,1"),_SCS("set_max_steer_angle"),_SCS("get_max_steer_angle"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/drive_torque",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_drive_torque"),_SCS("get_drive_torque"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/steer_rate",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_steer_rate"),_SCS("get_steer_rate"));
-
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_steering",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_steering"),_SCS("get_target_steering"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_accelerate",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_accelerate"),_SCS("get_target_accelerate"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/hand_brake",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_hand_brake"),_SCS("get_hand_brake"));
-
-}
-
-CarBody::CarBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
-
- forward_drive=true;
- backward_drive=true;
- max_steer_angle=30;
- steer_rate=1;
- drive_torque=520;
-
- target_steering=0;
- target_accelerate=0;
- hand_brake=0;
-
- steering=0;
- accelerate=0;
-
- mass=1;
- friction=1;
-
- ccd=false;
-// can_sleep=true;
-
-
-
-
- exclude.insert(get_rid());
- PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed");
-
-
-}
diff --git a/scene/3d/car_body.h b/scene/3d/car_body.h
deleted file mode 100644
index 87eb047bcf..0000000000
--- a/scene/3d/car_body.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*************************************************************************/
-/* car_body.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 CAR_BODY_H
-#define CAR_BODY_H
-
-#include "scene/3d/physics_body.h"
-
-
-class CarBody;
-
-class CarWheel : public Spatial {
-
- OBJ_TYPE(CarWheel,Spatial);
-
-friend class CarBody;
- real_t side_friction;
- real_t forward_friction;
- real_t travel;
- real_t radius;
- real_t resting_frac;
- real_t damping_frac;
- int num_rays;
- Transform local_xform;
-
- CarBody *body;
-
- float angVel;
- float steerAngle;
- float torque;
- float driveTorque;
- float axisAngle;
- float upSpeed; // speed relative to the car
- bool locked;
- // last frame stuff
- float lastDisplacement;
- float angVelForGrip;
- bool lastOnFloor;
-
- bool type_drive;
- bool type_steer;
-
-
-protected:
- void update(real_t dt);
- bool add_forces(PhysicsDirectBodyState *s);
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
- void set_side_friction(real_t p_friction);
- void set_forward_friction(real_t p_friction);
- void set_travel(real_t p_travel);
- void set_radius(real_t p_radius);
- void set_resting_frac(real_t p_frac);
- void set_damping_frac(real_t p_frac);
- void set_num_rays(real_t p_rays);
-
- real_t get_side_friction() const;
- real_t get_forward_friction() const;
- real_t get_travel() const;
- real_t get_radius() const;
- real_t get_resting_frac() const;
- real_t get_damping_frac() const;
- int get_num_rays() const;
-
- void set_type_drive(bool p_enable);
- bool is_type_drive() const;
-
- void set_type_steer(bool p_enable);
- bool is_type_steer() const;
-
- CarWheel();
-
-};
-
-
-
-class CarBody : public PhysicsBody {
-
- OBJ_TYPE(CarBody,PhysicsBody);
-
- real_t mass;
- real_t friction;
-
- Vector3 linear_velocity;
- Vector3 angular_velocity;
- bool ccd;
-
- real_t max_steer_angle;
- real_t steer_rate;
- int wheel_num_rays;
- real_t drive_torque;
-
-// control stuff
- real_t target_steering;
- real_t target_accelerate;
-
- bool forward_drive;
- bool backward_drive;
-
- real_t steering;
- real_t accelerate;
- real_t hand_brake;
- Set<RID> exclude;
-
-
-friend class CarWheel;
- Vector<CarWheel*> wheels;
-
- static void _bind_methods();
-
- void _direct_state_changed(Object *p_state);
-public:
-
-
- void set_mass(real_t p_mass);
- real_t get_mass() const;
-
- void set_friction(real_t p_friction);
- real_t get_friction() const;
-
- void set_max_steer_angle(real_t p_angle);
- void set_steer_rate(real_t p_rate);
- void set_drive_torque(real_t p_torque);
-
- real_t get_max_steer_angle() const;
- real_t get_steer_rate() const;
- real_t get_drive_torque() const;
-
-
- void set_target_steering(float p_steering);
- void set_target_accelerate(float p_accelerate);
- void set_hand_brake(float p_amont);
-
- real_t get_target_steering() const;
- real_t get_target_accelerate() const;
- real_t get_hand_brake() const;
-
-
- CarBody();
-};
-
-#endif // CAR_BODY_H
diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp
index 06564f5c49..9c388a2883 100644
--- a/scene/3d/collision_object.cpp
+++ b/scene/3d/collision_object.cpp
@@ -47,14 +47,20 @@ 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);
} else
PhysicsServer::get_singleton()->body_set_space(rid,space);
+ _update_pickable();
//get space
- }
+ };
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -64,6 +70,11 @@ void CollisionObject::_notification(int p_what) {
PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+
+ _update_pickable();
+
+ } break;
case NOTIFICATION_EXIT_WORLD: {
if (area) {
@@ -91,11 +102,11 @@ void CollisionObject::_update_shapes() {
continue;
if (area)
PhysicsServer::get_singleton()->area_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
- else {
+ else {
PhysicsServer::get_singleton()->body_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
- if (shapes[i].trigger)
- PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger);
- }
+ if (shapes[i].trigger)
+ PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger);
+ }
}
}
@@ -154,24 +165,24 @@ 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) );
}
}
-void CollisionObject::_input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape) {
+void CollisionObject::_input_event(Node *p_camera, const InputEvent& p_input_event, const Vector3& p_pos, const Vector3& p_normal, int p_shape) {
if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_input_event,p_pos,p_normal,p_shape);
+ get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_camera,p_input_event,p_pos,p_normal,p_shape);
}
- emit_signal(SceneStringNames::get_singleton()->input_event,p_input_event,p_pos,p_normal,p_shape);
+ emit_signal(SceneStringNames::get_singleton()->input_event,p_camera,p_input_event,p_pos,p_normal,p_shape);
}
void CollisionObject::_mouse_enter() {
@@ -192,6 +203,28 @@ void CollisionObject::_mouse_exit() {
}
+void CollisionObject::_update_pickable() {
+ if (!is_inside_tree())
+ return;
+ bool pickable = ray_pickable && is_inside_tree() && is_visible();
+ if (area)
+ PhysicsServer::get_singleton()->area_set_ray_pickable(rid,pickable);
+ else
+ PhysicsServer::get_singleton()->body_set_ray_pickable(rid,pickable);
+}
+
+void CollisionObject::set_ray_pickable(bool p_ray_pickable) {
+
+ ray_pickable=p_ray_pickable;
+ _update_pickable();
+
+}
+
+bool CollisionObject::is_ray_pickable() const {
+
+ return ray_pickable;
+}
+
void CollisionObject::_bind_methods() {
@@ -206,15 +239,18 @@ void CollisionObject::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform);
ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape);
ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject::clear_shapes);
+ ObjectTypeDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&CollisionObject::set_ray_pickable);
+ ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&CollisionObject::is_ray_pickable);
ObjectTypeDB::bind_method(_MD("set_capture_input_on_drag","enable"),&CollisionObject::set_capture_input_on_drag);
ObjectTypeDB::bind_method(_MD("get_capture_input_on_drag"),&CollisionObject::get_capture_input_on_drag);
ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject::get_rid);
- BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
+ BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
- ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
+ ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
ADD_SIGNAL( MethodInfo("mouse_enter"));
ADD_SIGNAL( MethodInfo("mouse_exit"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input/ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"input/capture_on_drag"),_SCS("set_capture_input_on_drag"),_SCS("get_capture_input_on_drag"));
}
@@ -296,6 +332,8 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) {
rid=p_rid;
area=p_area;
+ capture_input_on_drag=false;
+ ray_pickable=true;
if (p_area) {
PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
} else {
@@ -321,6 +359,7 @@ CollisionObject::CollisionObject() {
capture_input_on_drag=false;
+ ray_pickable=true;
//owner=
diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h
index afd73aa9cc..eafce2c82c 100644
--- a/scene/3d/collision_object.h
+++ b/scene/3d/collision_object.h
@@ -51,9 +51,10 @@ class CollisionObject : public Spatial {
};
bool capture_input_on_drag;
-
+ bool ray_pickable;
Vector<ShapeData> shapes;
+ void _update_pickable();
void _update_shapes();
friend class CollisionShape;
@@ -69,7 +70,7 @@ protected:
void _get_property_list( List<PropertyInfo> *p_list) const;
static void _bind_methods();
friend class Viewport;
- virtual void _input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape);
+ virtual void _input_event(Node* p_camera,const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape);
virtual void _mouse_enter();
virtual void _mouse_exit();
@@ -87,9 +88,13 @@ public:
void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
bool is_shape_set_as_trigger(int p_shape_idx) const;
+ void set_ray_pickable(bool p_ray_pickable);
+ bool is_ray_pickable() const;
+
void set_capture_input_on_drag(bool p_capture);
bool get_capture_input_on_drag() const;
+
_FORCE_INLINE_ RID get_rid() const { return rid; }
CollisionObject();
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/editable_shape.cpp b/scene/3d/editable_shape.cpp
deleted file mode 100644
index ab3f832028..0000000000
--- a/scene/3d/editable_shape.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*************************************************************************/
-/* editable_shape.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 "editable_shape.h"
-
-
-void EditableShape::_notification(int p_what) {
-
-
-
-}
-
-
-void EditableShape::set_bsp_tree(const BSP_Tree& p_bsp) {
-
- bsp=p_bsp;
-}
-
-void EditableShape::set_shape(const Ref<Shape>& p_shape) {
-
- shape=p_shape;
-}
-
-
-
-EditableShape::EditableShape()
-{
-}
-
-
-
-/////////////////////////
-
-
-void EditableSphere::set_radius(float p_radius) {
-
- radius=p_radius;
- update_gizmo();
- _change_notify("params/radius");
-}
-
-
-float EditableSphere::get_radius() const{
-
- return radius;
-}
-
-
-void EditableSphere::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("set_radius","radius"),&EditableSphere::set_radius);
- ObjectTypeDB::bind_method(_MD("get_radius"),&EditableSphere::get_radius);
-
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_EXP_RANGE,"0.001,16384,0.001"),_SCS("set_radius"),_SCS("get_radius"));
-}
-
-EditableSphere::EditableSphere() {
-
- radius=1.0;
-}
diff --git a/scene/3d/editable_shape.h b/scene/3d/editable_shape.h
deleted file mode 100644
index 9accea575c..0000000000
--- a/scene/3d/editable_shape.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*************************************************************************/
-/* editable_shape.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 EDITABLE_SHAPE_H
-#define EDITABLE_SHAPE_H
-
-#include "scene/3d/spatial.h"
-#include "scene/resources/shape.h"
-
-class EditableShape : public Spatial {
-
- OBJ_TYPE(EditableShape,Spatial);
-
- //can hold either of those
- BSP_Tree bsp;
- Ref<Shape> shape;
-
- void _update_parent();
-protected:
-
- void _notification(int p_what);
-
- void set_bsp_tree(const BSP_Tree& p_bsp);
- void set_shape(const Ref<Shape>& p_shape);
-public:
- EditableShape();
-};
-
-
-class EditableSphere : public EditableShape {
-
- OBJ_TYPE( EditableSphere, EditableShape );
-
-
- float radius;
-protected:
-
- static void _bind_methods();
-public:
-
- void set_radius(float p_radius);
- float get_radius() const;
-
- EditableSphere();
-};
-
-
-#endif // EDITABLE_SHAPE_H
diff --git a/scene/3d/follow_camera.cpp b/scene/3d/follow_camera.cpp
deleted file mode 100644
index e7ced6c2ba..0000000000
--- a/scene/3d/follow_camera.cpp
+++ /dev/null
@@ -1,778 +0,0 @@
-/*************************************************************************/
-/* follow_camera.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 "follow_camera.h"
-
-
-#include "physics_body.h"
-#include "scene/resources/surface_tool.h"
-
-void FollowCamera::_set_initial_orbit(const Vector2& p_orbit) {
-
- initial_orbit=p_orbit;
- set_orbit(p_orbit);
-}
-
-
-
-void FollowCamera::_clear_queries() {
-
- if (!queries_active)
- return;
-#if 0
- for(int i=0;i<3;i++)
- PhysicsServer::get_singleton()->query_clear(clip_ray[i].query);
-#endif
- queries_active=false;
-
-}
-
-void FollowCamera::_compute_camera() {
-
- // update the transform with the next proposed transform (camera is 1 logic frame delayed)
-
- /*
- float time = get_root_node()->get_frame_time();
- Vector3 oldp = accepted.get_origin();
- Vector3 newp = proposed.get_origin();
-
- float frame_dist = time *
- if (oldp.distance_to(newp) >
- */
-
- float time = get_process_delta_time();
- bool noblend=false;
-
- if (clip) {
-
- if ((clip_ray[0].clipped==clip_ray[2].clipped || fullclip) && clip_ray[1].clipped) {
- //all have been clipped
- proposed_pos=clip_ray[1].clip_pos-extraclip*(proposed_pos-target_pos).normalized();
- if (clip_ray[0].clipped)
- fullclip=true;
- noblend=true;
-
-
- } else {
-
-
- //Vector3 rel=follow_pos-target_pos;
-
- if (clip_ray[0].clipped && !clip_ray[2].clipped) {
-
- float distance = target_pos.distance_to(clip_ray[0].clip_pos);
- real_t amount = 1.0-(distance/clip_len);
- amount = CLAMP(amount,0,1)*autoturn_speed*time;
- if (clip_ray[1].clipped)
- amount*=2.0;
- //rotate_rel=Matrix3(Vector3(0,1,0),amount).xform(rel);
- rotate_orbit(Vector2(0,amount));
-
- } else if (clip_ray[2].clipped && !clip_ray[0].clipped) {
-
- float distance = target_pos.distance_to(clip_ray[2].clip_pos);
- real_t amount = 1.0-(distance/clip_len);
- amount = CLAMP(amount,0,1)*autoturn_speed*time;
- if (clip_ray[1].clipped)
- amount*=2.0;
- rotate_orbit(Vector2(0,-amount));
- }
-
- fullclip=false;
-
- }
- }
-
-
- Vector3 base_pos = get_global_transform().origin;
- Vector3 pull_from = base_pos;
- pull_from.y+=height; // height compensate
-
-
-
- Vector3 camera_target;
- if (use_lookat_target) {
-
- camera_target = lookat_target;
- } else {
- camera_target = base_pos;
- };
-
- Transform proposed;
- proposed.set_look_at(proposed_pos,camera_target,up_vector);
- proposed = proposed * Transform(Matrix3(Vector3(1,0,0),Math::deg2rad(inclination)),Vector3()); //inclination
-
-
- accepted=proposed;
- if (smooth && !noblend) {
-
-
- Vector3 vec1 = accepted.origin;
- Vector3 vec2 = final.origin;
- final.origin = vec2.linear_interpolate(vec1, MIN(1,smooth_pos_ratio * time));;
-
- Quat q1 = accepted.basis;
- Quat q2 = final.basis;
- final.basis = q2.slerp(q1, MIN(1,smooth_rot_ratio * time));
-
- } else {
- final=accepted;
- }
-
- _update_camera();
-
- // calculate the next proposed transform
-
-
- Vector3 new_pos;
-
- { /*follow code*/
-
-
-
- /* calculate some variables */
-
- Vector3 rel = follow_pos - pull_from;
-
- float l = rel.length();
- Vector3 rel_n = (l > 0) ? (rel/l) : Vector3();
- float ang = Math::acos(rel_n.dot( Vector3(0,1,0) ));
-
- Vector3 tangent = rel_n;
- tangent.y=0; // get rid of y
- if (tangent.length_squared() < CMP_EPSILON2)
- tangent=Vector3(0,0,1); // use Z as tangent if rel is parallel to y
- else
- tangent.normalize();
-
- /* now start applying the rules */
-
- //clip distance
- if (l > max_distance)
- l=max_distance;
- if (l < min_distance)
- l=min_distance;
-
- //fix angle
-
- float ang_min = Math_PI * 0.5 + Math::deg2rad(min_orbit_x);
- float ang_max = Math_PI * 0.5 + Math::deg2rad(max_orbit_x);
-
- if (ang<ang_min)
- ang=ang_min;
- if (ang>ang_max)
- ang=ang_max;
-
- /* finally, rebuild the validated camera position */
-
- new_pos=Vector3(0,Math::cos(ang),0);
- new_pos+=tangent*Math::sin(ang);
- new_pos*=l;
- new_pos+=pull_from;
- follow_pos=new_pos;
-
- }
-
- proposed_pos=new_pos;
-
- Vector3 rel = new_pos-camera_target;
-
-
- if (clip) {
-
- Vector<RID> exclude;
- exclude.push_back(target_body);
-
- for(int i=0;i<3;i++) {
-
- clip_ray[i].clipped=false;
- clip_ray[i].clip_pos=Vector3();
- clip_ray[i].cast_pos=camera_target;
-
- Vector3 cast_to = camera_target+Matrix3(Vector3(0,1,0),Math::deg2rad(autoturn_tolerance*(i-1.0))).xform(rel);
-
-
- if (i!=1) {
-
- Vector3 side = rel.cross(Vector3(0,1,0)).normalized()*(i-1.0);
- clip_ray[i].cast_pos+side*target_width+rel.normalized()*target_width;
-
- Vector3 d = -rel;
- d.rotate(Vector3(0,1,0),Math::deg2rad(get_fov())*(i-1.0));
- Plane p(new_pos,new_pos+d,new_pos+Vector3(0,1,0)); //fov clipping plane, build a face and use it as plane, facing doesn't matter
- Vector3 intersect;
- if (p.intersects_segment(clip_ray[i].cast_pos,cast_to,&intersect))
- cast_to=intersect;
-
- } else {
-
- cast_to+=rel.normalized()*extraclip;
- }
-
- // PhysicsServer::get_singleton()->query_intersection(clip_ray[i].query,get_world()->get_space(),exclude);
- // PhysicsServer::get_singleton()->query_intersection_segment(clip_ray[i].query,clip_ray[i].cast_pos,cast_to);
-
-
-
-
- }
-
- queries_active=true;
- } else {
-
- _clear_queries();
- }
- target_pos=camera_target;
- clip_len=rel.length();
-
-}
-
-void FollowCamera::set_use_lookat_target(bool p_use, const Vector3 &p_lookat) {
-
- use_lookat_target = p_use;
- lookat_target = p_lookat;
-};
-
-
-void FollowCamera::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_PROCESS: {
-
-
- _compute_camera();
- } break;
-
- case NOTIFICATION_ENTER_WORLD: {
-
- set_orbit(orbit);
- set_distance(distance);
-
- accepted=final=get_global_transform();
- proposed_pos=accepted.origin;
-
- target_body = RID();
-/*
- Node* parent = get_parent();
- while (parent) {
- PhysicsBody* p = parent->cast_to<PhysicsBody>();
- if (p) {
- target_body = p->get_body();
- break;
- };
- parent = parent->get_parent();
- };
-*/
- set_process(true);
-
- } break;
- case NOTIFICATION_TRANSFORM_CHANGED: {
-
- } break;
- case NOTIFICATION_EXIT_WORLD: {
-
- distance=get_distance();
- orbit=get_orbit();
- _clear_queries();
-
- } break;
- case NOTIFICATION_BECAME_CURRENT: {
-
- set_process(true);
- } break;
- case NOTIFICATION_LOST_CURRENT: {
-
- set_process(false);
- _clear_queries();
-
- } break;
- }
-
-}
-
-
-
-void FollowCamera::set_orbit(const Vector2& p_orbit) {
-
- orbit=p_orbit;
-
- if(is_inside_scene()) {
-
- Vector3 char_pos = get_global_transform().origin;
- char_pos.y+=height;
- float d = char_pos.distance_to(follow_pos);
-
- Matrix3 m;
- m.rotate(Vector3(0,1,0),orbit.y);
- m.rotate(Vector3(1,0,0),orbit.x);
-
- follow_pos=char_pos + m.get_axis(2) * d;
-
- }
-
- update_gizmo();
-
-}
-void FollowCamera::set_orbit_x(float p_x) {
-
- orbit.x=p_x;
- if(is_inside_scene())
- set_orbit(Vector2( p_x, get_orbit().y ));
-}
-void FollowCamera::set_orbit_y(float p_y) {
-
-
- orbit.y=p_y;
- if(is_inside_scene())
- set_orbit(Vector2( get_orbit().x, p_y ));
-
-}
-Vector2 FollowCamera::get_orbit() const {
-
-
- if (is_inside_scene()) {
-
- Vector3 char_pos = get_global_transform().origin;
- char_pos.y+=height;
- Vector3 rel = (follow_pos - char_pos).normalized();
- Vector2 ret_orbit;
- ret_orbit.x = Math::acos( Vector3(0,1,0).dot( rel ) ) - Math_PI * 0.5;
- ret_orbit.y = Math::atan2(rel.x,rel.z);
- return ret_orbit;
- }
- return orbit;
-}
-
-void FollowCamera::rotate_orbit(const Vector2& p_relative) {
-
- if (is_inside_scene()) {
-
- Matrix3 m;
- m.rotate(Vector3(0,1,0),Math::deg2rad(p_relative.y));
- m.rotate(Vector3(1,0,0),Math::deg2rad(p_relative.x));
-
- Vector3 char_pos = get_global_transform().origin;
- char_pos.y+=height;
- Vector3 rel = (follow_pos - char_pos);
- rel = m.xform(rel);
- follow_pos=char_pos+rel;
-
- }
-
- orbit+=p_relative;
- update_gizmo();
-}
-
-void FollowCamera::set_height(float p_height) {
-
-
- height=p_height;
- update_gizmo();
-}
-
-float FollowCamera::get_height() const {
-
- return height;
-
-}
-
-void FollowCamera::set_max_orbit_x(float p_max) {
-
- max_orbit_x=p_max;
- update_gizmo();
-}
-
-float FollowCamera::get_max_orbit_x() const {
-
- return max_orbit_x;
-}
-
-void FollowCamera::set_min_orbit_x(float p_min) {
-
- min_orbit_x=p_min;
- update_gizmo();
-}
-
-float FollowCamera::get_min_orbit_x() const {
-
- return min_orbit_x;
-}
-
-float FollowCamera::get_min_distance() const {
-
- return min_distance;
-}
-float FollowCamera::get_max_distance() const {
-
- return max_distance;
-}
-
-void FollowCamera::set_min_distance(float p_min) {
-
- min_distance=p_min;
- update_gizmo();
-}
-
-void FollowCamera::set_max_distance(float p_max) {
-
- max_distance = p_max;
- update_gizmo();
-}
-
-
-void FollowCamera::set_distance(float p_distance) {
-
- if (is_inside_scene()) {
-
- Vector3 char_pos = get_global_transform().origin;
- char_pos.y+=height;
- Vector3 rel = (follow_pos - char_pos).normalized();
- rel*=p_distance;
- follow_pos=char_pos+rel;
-
- }
-
- distance=p_distance;
-}
-
-float FollowCamera::get_distance() const {
-
- if (is_inside_scene()) {
-
- Vector3 char_pos = get_global_transform().origin;
- char_pos.y+=height;
- return (follow_pos - char_pos).length();
-
- }
-
- return distance;
-}
-
-void FollowCamera::set_clip(bool p_enabled) {
-
-
- clip=p_enabled;
-
- if (!p_enabled)
- _clear_queries();
-}
-
-bool FollowCamera::has_clip() const {
-
- return clip;
-
-}
-
-
-void FollowCamera::set_autoturn(bool p_enabled) {
-
-
- autoturn=p_enabled;
-}
-
-bool FollowCamera::has_autoturn() const {
-
- return autoturn;
-
-}
-
-void FollowCamera::set_autoturn_tolerance(float p_degrees) {
-
-
- autoturn_tolerance=p_degrees;
-}
-float FollowCamera::get_autoturn_tolerance() const {
-
-
- return autoturn_tolerance;
-}
-
-void FollowCamera::set_inclination(float p_degrees) {
-
-
- inclination=p_degrees;
-}
-float FollowCamera::get_inclination() const {
-
-
- return inclination;
-}
-
-
-void FollowCamera::set_autoturn_speed(float p_speed) {
-
-
- autoturn_speed=p_speed;
-}
-
-float FollowCamera::get_autoturn_speed() const {
-
- return autoturn_speed;
-
-}
-
-
-RES FollowCamera::_get_gizmo_geometry() const {
-
- Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
-
- Ref<FixedMaterial> mat( memnew( FixedMaterial ));
-
- mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(1.0,0.5,1.0,0.3) );
- mat->set_line_width(4);
- mat->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- mat->set_flag(Material::FLAG_UNSHADED,true);
-// mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
-
- surface_tool->begin(Mesh::PRIMITIVE_LINES);
- surface_tool->set_material(mat);
-
-
- int steps=16;
-
- Vector3 base_up = Matrix3(Vector3(1,0,0),Math::deg2rad(max_orbit_x)).get_axis(2);
- Vector3 base_down = Matrix3(Vector3(1,0,0),Math::deg2rad(min_orbit_x)).get_axis(2);
-
- Vector3 ofs(0,height,0);
-
- for(int i=0;i<steps;i++) {
-
-
- Matrix3 rot(Vector3(0,1,0),Math_PI*2*float(i)/steps);
- Matrix3 rot2(Vector3(0,1,0),Math_PI*2*float(i+1)/steps);
-
- Vector3 up = rot.xform(base_up);
- Vector3 up2 = rot2.xform(base_up);
-
- Vector3 down = rot.xform(base_down);
- Vector3 down2 = rot2.xform(base_down);
-
- surface_tool->add_vertex(ofs+up*min_distance);
- surface_tool->add_vertex(ofs+up*max_distance);
- surface_tool->add_vertex(ofs+up*min_distance);
- surface_tool->add_vertex(ofs+up2*min_distance);
- surface_tool->add_vertex(ofs+up*max_distance);
- surface_tool->add_vertex(ofs+up2*max_distance);
-
- surface_tool->add_vertex(ofs+down*min_distance);
- surface_tool->add_vertex(ofs+down*max_distance);
- surface_tool->add_vertex(ofs+down*min_distance);
- surface_tool->add_vertex(ofs+down2*min_distance);
- surface_tool->add_vertex(ofs+down*max_distance);
- surface_tool->add_vertex(ofs+down2*max_distance);
-
- int substeps = 8;
-
- for(int j=0;j<substeps;j++) {
-
- Vector3 a = up.linear_interpolate(down,float(j)/substeps).normalized()*max_distance;
- Vector3 b = up.linear_interpolate(down,float(j+1)/substeps).normalized()*max_distance;
- Vector3 am = up.linear_interpolate(down,float(j)/substeps).normalized()*min_distance;
- Vector3 bm = up.linear_interpolate(down,float(j+1)/substeps).normalized()*min_distance;
-
- surface_tool->add_vertex(ofs+a);
- surface_tool->add_vertex(ofs+b);
- surface_tool->add_vertex(ofs+am);
- surface_tool->add_vertex(ofs+bm);
-
- }
- }
-
-
- return surface_tool->commit();
-
-
-}
-
-
-void FollowCamera::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("_set_initial_orbit","orbit"),&FollowCamera::_set_initial_orbit);
- ObjectTypeDB::bind_method(_MD("set_orbit","orbit"),&FollowCamera::set_orbit);
- ObjectTypeDB::bind_method(_MD("get_orbit"),&FollowCamera::get_orbit);
- ObjectTypeDB::bind_method(_MD("set_orbit_x","x"),&FollowCamera::set_orbit_x);
- ObjectTypeDB::bind_method(_MD("set_orbit_y","y"),&FollowCamera::set_orbit_y);
- ObjectTypeDB::bind_method(_MD("set_min_orbit_x","x"),&FollowCamera::set_min_orbit_x);
- ObjectTypeDB::bind_method(_MD("get_min_orbit_x"),&FollowCamera::get_min_orbit_x);
- ObjectTypeDB::bind_method(_MD("set_max_orbit_x","x"),&FollowCamera::set_max_orbit_x);
- ObjectTypeDB::bind_method(_MD("get_max_orbit_x"),&FollowCamera::get_max_orbit_x);
- ObjectTypeDB::bind_method(_MD("set_height","height"),&FollowCamera::set_height);
- ObjectTypeDB::bind_method(_MD("get_height"),&FollowCamera::get_height);
- ObjectTypeDB::bind_method(_MD("set_inclination","inclination"),&FollowCamera::set_inclination);
- ObjectTypeDB::bind_method(_MD("get_inclination"),&FollowCamera::get_inclination);
-
- ObjectTypeDB::bind_method(_MD("rotate_orbit"),&FollowCamera::rotate_orbit);
- ObjectTypeDB::bind_method(_MD("set_distance","distance"),&FollowCamera::set_distance);
- ObjectTypeDB::bind_method(_MD("get_distance"),&FollowCamera::get_distance);
- ObjectTypeDB::bind_method(_MD("set_max_distance","max_distance"),&FollowCamera::set_max_distance);
- ObjectTypeDB::bind_method(_MD("get_max_distance"),&FollowCamera::get_max_distance);
- ObjectTypeDB::bind_method(_MD("set_min_distance","min_distance"),&FollowCamera::set_min_distance);
- ObjectTypeDB::bind_method(_MD("get_min_distance"),&FollowCamera::get_min_distance);
- ObjectTypeDB::bind_method(_MD("set_clip","enable"),&FollowCamera::set_clip);
- ObjectTypeDB::bind_method(_MD("has_clip"),&FollowCamera::has_clip);
- ObjectTypeDB::bind_method(_MD("set_autoturn","enable"),&FollowCamera::set_autoturn);
- ObjectTypeDB::bind_method(_MD("has_autoturn"),&FollowCamera::has_autoturn);
- ObjectTypeDB::bind_method(_MD("set_autoturn_tolerance","degrees"),&FollowCamera::set_autoturn_tolerance);
- ObjectTypeDB::bind_method(_MD("get_autoturn_tolerance"),&FollowCamera::get_autoturn_tolerance);
- ObjectTypeDB::bind_method(_MD("set_autoturn_speed","speed"),&FollowCamera::set_autoturn_speed);
- ObjectTypeDB::bind_method(_MD("get_autoturn_speed"),&FollowCamera::get_autoturn_speed);
- ObjectTypeDB::bind_method(_MD("set_smoothing","enable"),&FollowCamera::set_smoothing);
- ObjectTypeDB::bind_method(_MD("has_smoothing"),&FollowCamera::has_smoothing);
- ObjectTypeDB::bind_method(_MD("set_rotation_smoothing","amount"),&FollowCamera::set_rotation_smoothing);
- ObjectTypeDB::bind_method(_MD("get_rotation_smoothing"),&FollowCamera::get_rotation_smoothing);
- ObjectTypeDB::bind_method(_MD("set_translation_smoothing","amount"),&FollowCamera::set_translation_smoothing);
- ObjectTypeDB::bind_method(_MD("get_translation_smoothing"),&FollowCamera::get_translation_smoothing);
- ObjectTypeDB::bind_method(_MD("set_use_lookat_target","use","lookat"),&FollowCamera::set_use_lookat_target, DEFVAL(Vector3()));
- ObjectTypeDB::bind_method(_MD("set_up_vector","vector"),&FollowCamera::set_up_vector);
- ObjectTypeDB::bind_method(_MD("get_up_vector"),&FollowCamera::get_up_vector);
-
- ObjectTypeDB::bind_method(_MD("_ray_collision"),&FollowCamera::_ray_collision);
-
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "orbit" ), _SCS("_set_initial_orbit"),_SCS("get_orbit") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,0.01" ), _SCS("set_height"), _SCS("get_height") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "inclination", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_inclination"), _SCS("get_inclination") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_max_orbit_x"), _SCS("get_max_orbit_x") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_min_orbit_x"), _SCS("get_min_orbit_x") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_min_distance"), _SCS("get_min_distance") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_max_distance"), _SCS("get_max_distance") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "distance", PROPERTY_HINT_RANGE,"0.01,1024,0,01"), _SCS("set_distance"), _SCS("get_distance") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "clip"), _SCS("set_clip"), _SCS("has_clip") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "autoturn"), _SCS("set_autoturn"), _SCS("has_autoturn") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_tolerance", PROPERTY_HINT_RANGE,"1,90,0.01") , _SCS("set_autoturn_tolerance"), _SCS("get_autoturn_tolerance") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_speed", PROPERTY_HINT_RANGE,"1,90,0.01"), _SCS("set_autoturn_speed"), _SCS("get_autoturn_speed") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "smoothing"), _SCS("set_smoothing"), _SCS("has_smoothing") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "translation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_translation_smoothing"), _SCS("get_translation_smoothing") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "rotation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_rotation_smoothing"), _SCS("get_rotation_smoothing") );
-
-
-}
-
-void FollowCamera::_ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx) {
-
- clip_ray[p_idx].clip_pos=p_point;
- clip_ray[p_idx].clipped=true;
-
-};
-
-Transform FollowCamera::get_camera_transform() const {
-
- return final;
-}
-
-void FollowCamera::set_smoothing(bool p_enable) {
-
- smooth=p_enable;
-}
-
-bool FollowCamera::has_smoothing() const {
-
- return smooth;
-}
-
-void FollowCamera::set_translation_smoothing(float p_amount) {
-
- smooth_pos_ratio=p_amount;
-}
-float FollowCamera::get_translation_smoothing() const {
-
- return smooth_pos_ratio;
-}
-
-void FollowCamera::set_rotation_smoothing(float p_amount) {
-
- smooth_rot_ratio=p_amount;
-
-}
-
-void FollowCamera::set_up_vector(const Vector3& p_up) {
-
- up_vector=p_up;
-}
-
-Vector3 FollowCamera::get_up_vector() const{
-
- return up_vector;
-}
-
-float FollowCamera::get_rotation_smoothing() const {
-
- return smooth_pos_ratio;
-
-}
-
-
-FollowCamera::FollowCamera() {
-
-
- height=1;
-
- orbit=Vector2(0,0);
- up_vector=Vector3(0,1,0);
-
- distance=3;
- min_distance=2;
- max_distance=5;
-
- autoturn=true;
- autoturn_tolerance=10;
- autoturn_speed=80;
-
- min_orbit_x=-50;
- max_orbit_x=70;
- inclination=0;
- target_width=0.3;
-
- clip=true;
- use_lookat_target = false;
- extraclip=0.3;
- fullclip=false;
-
- smooth=true;
- smooth_rot_ratio=10;
- smooth_pos_ratio=10;
-
-
- for(int i=0;i<3;i++) {
-// clip_ray[i].query=PhysicsServer::get_singleton()->query_create(this, "_ray_collision", i, true);
- clip_ray[i].clipped=false;
- }
-
- queries_active=false;
-
-
-}
-
-FollowCamera::~FollowCamera() {
-
- for(int i=0;i<3;i++) {
- PhysicsServer::get_singleton()->free(clip_ray[i].query);
- }
-
-
-}
diff --git a/scene/3d/follow_camera.h b/scene/3d/follow_camera.h
deleted file mode 100644
index 10912eb606..0000000000
--- a/scene/3d/follow_camera.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*************************************************************************/
-/* follow_camera.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 FOLLOW_CAMERA_H
-#define FOLLOW_CAMERA_H
-
-#include "scene/3d/camera.h"
-
-class FollowCamera : public Camera {
-
- OBJ_TYPE( FollowCamera, Camera );
-
-private:
-
-
- //used for follow
- Vector3 follow_pos;
- //used for fixed
- Vector2 initial_orbit;
- Vector2 orbit;
- float distance;
-
- float height;
- float target_width;
-
- float min_distance;
- float max_distance;
-
- float max_orbit_x;
- float min_orbit_x;
-
- float inclination;
- float extraclip;
- bool fullclip;
-
- bool clip;
- bool autoturn;
- float autoturn_tolerance;
- float autoturn_speed;
-
- bool smooth;
- float smooth_rot_ratio;
- float smooth_pos_ratio;
-
-
-
- struct ClipRay {
- RID query;
- bool clipped;
- Vector3 cast_pos;
- Vector3 clip_pos;
- };
-
- ClipRay clip_ray[3];
- Vector3 target_pos;
- float clip_len;
-
- Vector3 up_vector;
-
-
- virtual RES _get_gizmo_geometry() const;
-
- Transform ted;
- Vector3 proposed_pos;
- Transform accepted;
- Transform final;
- RID target_body;
-
- bool use_lookat_target;
- Vector3 lookat_target;
-
- void _compute_camera();
-
- bool queries_active;
- void _clear_queries();
-
- void _set_initial_orbit(const Vector2& p_orbit);
-
-protected:
-
- virtual void _request_camera_update() {} //ignore
-
- void _notification(int p_what);
-
- static void _bind_methods();
-
- void _ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx);
-
-public:
-
-
- void set_orbit(const Vector2& p_orbit);
- void set_orbit_x(float p_x);
- void set_orbit_y(float p_y);
- Vector2 get_orbit() const;
-
- void set_height(float p_height);
- float get_height() const;
-
- void set_inclination(float p_degrees);
- float get_inclination() const;
-
- void set_max_orbit_x(float p_max);
- float get_max_orbit_x() const;
-
- void set_min_orbit_x(float p_min);
- float get_min_orbit_x() const;
-
- void rotate_orbit(const Vector2& p_relative);
-
- void set_distance(float p_distance);
- float get_distance() const;
-
- float get_min_distance() const;
- float get_max_distance() const;
- void set_min_distance(float p_min);
- void set_max_distance(float p_max);
-
- /** FINISH THIS AND CLEAN IT UP */
-
- void set_clip(bool p_enabled);
- bool has_clip() const;
-
- void set_autoturn(bool p_enabled);
- bool has_autoturn() const;
-
- void set_autoturn_tolerance(float p_degrees);
- float get_autoturn_tolerance() const;
-
- void set_autoturn_speed(float p_speed);
- float get_autoturn_speed() const;
-
- void set_smoothing(bool p_enable);
- bool has_smoothing() const;
-
- void set_translation_smoothing(float p_amount);
- float get_translation_smoothing() const;
-
- void set_rotation_smoothing(float p_amount);
- float get_rotation_smoothing() const;
-
- void set_use_lookat_target(bool p_use, const Vector3 &p_lookat = Vector3());
-
- void set_up_vector(const Vector3& p_up);
- Vector3 get_up_vector() const;
-
- virtual Transform get_camera_transform() const;
-
- FollowCamera();
- ~FollowCamera();
-};
-
-
-
-#endif // FOLLOW_CAMERA_H
diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp
index 1459f2c362..651d20ae71 100644
--- a/scene/3d/immediate_geometry.cpp
+++ b/scene/3d/immediate_geometry.cpp
@@ -72,6 +72,53 @@ DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const {
return DVector<Face3>();
}
+
+
+void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) {
+
+ for(int i = 1; i <= p_lats; i++) {
+ double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats);
+ double z0 = Math::sin(lat0);
+ double zr0 = Math::cos(lat0);
+
+ double lat1 = Math_PI * (-0.5 + (double) i / p_lats);
+ double z1 = Math::sin(lat1);
+ double zr1 = Math::cos(lat1);
+
+ for(int j = p_lons; j >= 1; j--) {
+
+ double lng0 = 2 * Math_PI * (double) (j - 1) / p_lons;
+ double x0 = Math::cos(lng0);
+ double y0 = Math::sin(lng0);
+
+ double lng1 = 2 * Math_PI * (double) (j) / p_lons;
+ double x1 = Math::cos(lng1);
+ double y1 = Math::sin(lng1);
+
+
+ Vector3 v[4]={
+ Vector3(x1 * zr0, z0, y1 *zr0),
+ Vector3(x1 * zr1, z1, y1 *zr1),
+ Vector3(x0 * zr1, z1, y0 *zr1),
+ Vector3(x0 * zr0, z0, y0 *zr0)
+ };
+
+#define ADD_POINT(m_idx)\
+ set_normal(v[m_idx]);\
+ add_vertex(v[m_idx]*p_radius);
+
+ ADD_POINT(0);
+ ADD_POINT(1);
+ ADD_POINT(2);
+
+ ADD_POINT(2);
+ ADD_POINT(3);
+ ADD_POINT(0);
+ }
+ }
+
+}
+
void ImmediateGeometry::_bind_methods() {
ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin);
@@ -80,12 +127,15 @@ 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);
}
+
+
ImmediateGeometry::ImmediateGeometry() {
im = VisualServer::get_singleton()->immediate_create();
diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h
index 2db81134c6..beb8ea8214 100644
--- a/scene/3d/immediate_geometry.h
+++ b/scene/3d/immediate_geometry.h
@@ -31,6 +31,11 @@ public:
void end();
void clear();
+
+ void add_sphere(int p_lats,int p_lons,float p_radius);
+
+
+
virtual AABB get_aabb() const;
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
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 1efc74e672..15e77e5378 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?
@@ -429,10 +429,42 @@ void Light::approximate_opengl_attenuation(float p_constant, float p_linear, flo
}
+
+void Light::_update_visibility() {
+
+ if (!is_inside_tree())
+ return;
+
+
+bool editor_ok=true;
+
+#ifdef TOOLS_ENABLED
+ if (editor_only) {
+ if (!get_tree()->is_editor_hint()) {
+ editor_ok=false;
+ } else {
+ editor_ok = (get_tree()->get_edited_scene_root() && (this==get_tree()->get_edited_scene_root() || get_owner()==get_tree()->get_edited_scene_root()));
+ }
+ }
+#endif
+
+ VS::get_singleton()->instance_light_set_enabled(get_instance(),is_visible() && enabled && editor_ok);
+ _change_notify("geometry/visible");
+
+}
+
+
+void Light::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE || p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+ _update_visibility();
+ }
+}
+
void Light::set_enabled(bool p_enabled) {
enabled=p_enabled;
- VS::get_singleton()->instance_light_set_enabled(get_instance(),enabled);
+ _update_visibility();
}
bool Light::is_enabled() const{
@@ -440,6 +472,17 @@ bool Light::is_enabled() const{
return enabled;
}
+void Light::set_editor_only(bool p_editor_only) {
+
+ editor_only=p_editor_only;
+ _update_visibility();
+}
+
+bool Light::is_editor_only() const{
+
+ return editor_only;
+}
+
void Light::_bind_methods() {
@@ -457,9 +500,12 @@ void Light::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_bake_mode"), &Light::get_bake_mode );
ObjectTypeDB::bind_method(_MD("set_enabled","enabled"), &Light::set_enabled );
ObjectTypeDB::bind_method(_MD("is_enabled"), &Light::is_enabled );
+ ObjectTypeDB::bind_method(_MD("set_editor_only","editor_only"), &Light::set_editor_only );
+ ObjectTypeDB::bind_method(_MD("is_editor_only"), &Light::is_editor_only );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/enabled"), _SCS("set_enabled"), _SCS("is_enabled"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/editor_only"), _SCS("set_editor_only"), _SCS("is_editor_only"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "params/bake_mode",PROPERTY_HINT_ENUM,"Disabled,Indirect,Indirect+Shadows,Full"), _SCS("set_bake_mode"), _SCS("get_bake_mode"));
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/energy", PROPERTY_HINT_EXP_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ENERGY );
/*
@@ -531,6 +577,7 @@ Light::Light(VisualServer::LightType p_type) {
set_project_shadows( false );
set_base(light);
enabled=true;
+ editor_only=false;
bake_mode=BAKE_MODE_DISABLED;
}
@@ -622,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_ATTENUATION );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION );
}
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 8e7395fd84..6fb57a269b 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -92,8 +92,10 @@ private:
VisualServer::LightType type;
bool shadows;
bool enabled;
+ bool editor_only;
Operator op;
-
+
+ void _update_visibility();
// bind helpers
protected:
@@ -104,6 +106,7 @@ protected:
virtual RES _get_gizmo_geometry() const;
static void _bind_methods();
+ void _notification(int p_what);
Light(VisualServer::LightType p_type);
@@ -132,6 +135,9 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const;
+ void set_editor_only(bool p_editor_only);
+ bool is_editor_only() const;
+
virtual AABB get_aabb() const;
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index 40981d468e..d7266e5df7 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -30,7 +30,7 @@
#include "skeleton.h"
#include "physics_body.h"
-
+#include "body_shape.h"
bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
@@ -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();
}
@@ -181,6 +181,11 @@ void MeshInstance::create_trimesh_collision() {
add_child(static_body);
if (get_owner())
static_body->set_owner( get_owner() );
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(static_body->get_shape(0));
+ static_body->add_child(cshape);
+ if (get_owner())
+ cshape->set_owner( get_owner() );
}
@@ -210,12 +215,18 @@ void MeshInstance::create_convex_collision() {
add_child(static_body);
if (get_owner())
static_body->set_owner( get_owner() );
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(static_body->get_shape(0));
+ static_body->add_child(cshape);
+ if (get_owner())
+ cshape->set_owner( get_owner() );
+
}
void MeshInstance::_notification(int p_what) {
- if (p_what==NOTIFICATION_ENTER_SCENE) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
_resolve_skeleton_path();
}
}
@@ -229,9 +240,9 @@ void MeshInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_skeleton_path:NodePath"),&MeshInstance::get_skeleton_path);
ObjectTypeDB::bind_method(_MD("get_aabb"),&MeshInstance::get_aabb);
ObjectTypeDB::bind_method(_MD("create_trimesh_collision"),&MeshInstance::create_trimesh_collision);
- ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT);
ObjectTypeDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision);
- ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT);
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh/mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh"));
ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "mesh/skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path"));
}
diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp
index d2abdad079..ce002fb44b 100644
--- a/scene/3d/navigation.cpp
+++ b/scene/3d/navigation.cpp
@@ -21,6 +21,7 @@ void Navigation::_navmesh_link(int p_id) {
List<Polygon>::Element *P=nm.polygons.push_back(Polygon());
Polygon &p=P->get();
+ p.owner=&nm;
Vector<int> poly = nm.navmesh->get_polygon(i);
int plen=poly.size();
@@ -145,13 +146,14 @@ void Navigation::_navmesh_unlink(int p_id) {
}
-int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform) {
+int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh, const Transform& p_xform, Object *p_owner) {
int id = last_id++;
NavMesh nm;
nm.linked=false;
nm.navmesh=p_mesh;
nm.xform=p_xform;
+ nm.owner=p_owner;
navmesh_map[id]=nm;
_navmesh_link(id);
@@ -180,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) {
@@ -377,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);
@@ -394,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);
@@ -453,6 +496,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
bool use_collision=false;
Vector3 closest_point;
float closest_point_d=1e20;
+ NavMesh *closest_navmesh=NULL;
for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
@@ -471,10 +515,12 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
closest_point=inters;
use_collision=true;
closest_point_d=p_from.distance_to(inters);
+ closest_navmesh=p.owner;
} else if (closest_point_d > inters.distance_to(p_from)){
closest_point=inters;
closest_point_d=p_from.distance_to(inters);
+ closest_navmesh=p.owner;
}
}
}
@@ -492,6 +538,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
closest_point_d=d;
closest_point=b;
+ closest_navmesh=p.owner;
}
}
@@ -499,6 +546,10 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
}
}
+ if (closest_navmesh && closest_navmesh->owner) {
+ //print_line("navmesh is: "+closest_navmesh->owner->cast_to<Node>()->get_name());
+ }
+
return closest_point;
}
@@ -577,7 +628,7 @@ Vector3 Navigation::get_up_vector() const{
void Navigation::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform"),&Navigation::navmesh_create);
+ ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform","owner"),&Navigation::navmesh_create,DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform);
ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);
diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h
index e8a97a6591..69d48531a7 100644
--- a/scene/3d/navigation.h
+++ b/scene/3d/navigation.h
@@ -41,6 +41,8 @@ class Navigation : public Spatial {
};
+ struct NavMesh;
+
struct Polygon {
@@ -57,6 +59,8 @@ class Navigation : public Spatial {
float distance;
int prev_edge;
+
+ NavMesh *owner;
};
@@ -74,6 +78,7 @@ class Navigation : public Spatial {
struct NavMesh {
+ Object *owner;
Transform xform;
bool linked;
Ref<NavigationMesh> navmesh;
@@ -113,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:
@@ -124,7 +130,7 @@ public:
Vector3 get_up_vector() const;
//API should be as dynamic as possible
- int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform);
+ int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform,Object* p_owner=NULL);
void navmesh_set_transform(int p_id, const Transform& p_xform);
void navmesh_remove(int p_id);
diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp
index cf2e22a573..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) {
@@ -129,7 +129,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) {
if (navmesh.is_valid()) {
- nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+ nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
}
}
@@ -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) {
@@ -162,7 +162,7 @@ void NavigationMeshInstance::_notification(int p_what) {
if (enabled && navmesh.is_valid()) {
- nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+ nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
}
break;
}
@@ -178,7 +178,7 @@ void NavigationMeshInstance::_notification(int p_what) {
}
} break;
- case NOTIFICATION_EXIT_SCENE: {
+ case NOTIFICATION_EXIT_TREE: {
if (navigation) {
@@ -205,7 +205,7 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh>& p_na
navmesh=p_navmesh;
if (navigation && navmesh.is_valid() && enabled) {
- nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+ nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
}
update_gizmo();
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 a99964cc54..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++) {
@@ -245,46 +246,48 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,
if (!E) {
E = contact_monitor->body_map.insert(objid,BodyState());
- E->get().rc=0;
- E->get().in_scene=node && node->is_inside_scene();
+ //E->get().rc=0;
+ 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);
}
}
}
- E->get().rc++;
+ //E->get().rc++;
if (node)
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);
}
} else {
- E->get().rc--;
+ //E->get().rc--;
if (node)
E->get().shapes.erase(ShapePair(p_body_shape,p_local_shape));
- if (E->get().rc==0) {
+ 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 (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 (in_tree)
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
}
contact_monitor->body_map.erase(E);
}
- if (node && E->get().in_scene) {
+ if (node && in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_local_shape);
}
@@ -635,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);
@@ -680,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"));
@@ -790,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;
@@ -827,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;
@@ -905,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;
@@ -965,6 +995,7 @@ Vector3 KinematicBody::move(const Vector3& p_motion) {
normal=rest.normal;
collider=rest.collider_id;
collider_vel=rest.linear_velocity;
+ collider_shape=rest.shape;
}
}
@@ -986,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);
@@ -1015,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)
@@ -1026,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;
}
@@ -1053,7 +1086,12 @@ ObjectID KinematicBody::get_collider() const {
ERR_FAIL_COND_V(!colliding,0);
return collider;
}
+int KinematicBody::get_collider_shape() const {
+ ERR_FAIL_COND_V(!colliding,-1);
+ return collider_shape;
+
+}
void KinematicBody::set_collide_with_static_bodies(bool p_enable) {
collide_static=p_enable;
@@ -1117,6 +1155,7 @@ void KinematicBody::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody::get_collision_normal);
ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody::get_collider_velocity);
ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody::_get_collider);
+ ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody::get_collider_shape);
ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody::set_collide_with_static_bodies);
@@ -1153,6 +1192,7 @@ KinematicBody::KinematicBody() : PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC)
colliding=false;
collider=0;
margin=0.001;
+ collider_shape=0;
}
KinematicBody::~KinematicBody() {
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 442921302e..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();
};
@@ -162,8 +164,8 @@ private:
};
struct BodyState {
- int rc;
- bool in_scene;
+ //int rc;
+ 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);
@@ -266,6 +269,8 @@ class KinematicBody : public PhysicsBody {
Vector3 normal;
Vector3 collider_vel;
ObjectID collider;
+ int collider_shape;
+
Variant _get_collider() const;
@@ -291,6 +296,7 @@ public:
Vector3 get_collision_normal() const;
Vector3 get_collider_velocity() const;
ObjectID get_collider() const;
+ int get_collider_shape() const;
void set_collide_with_static_bodies(bool p_enable);
bool can_collide_with_static_bodies() const;
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index 341b02314d..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;
@@ -66,6 +66,9 @@ void Joint::_update_joint(bool p_only_free) {
joint = _configure_joint(body_a,body_b);
+ if (joint.is_valid())
+ PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority);
+
if (body_b && joint.is_valid()) {
ba=body_a->get_rid();
@@ -107,6 +110,20 @@ NodePath Joint::get_node_b() const{
}
+void Joint::set_solver_priority(int p_priority) {
+
+ solver_priority=p_priority;
+ if (joint.is_valid())
+ PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority);
+
+}
+
+int Joint::get_solver_priority() const {
+
+ return solver_priority;
+}
+
+
void Joint::_notification(int p_what) {
switch(p_what) {
@@ -114,11 +131,9 @@ 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);
joint=RID();
}
@@ -138,9 +153,13 @@ void Joint::_bind_methods() {
ObjectTypeDB::bind_method( _MD("set_node_b","node"), &Joint::set_node_b );
ObjectTypeDB::bind_method( _MD("get_node_b"), &Joint::get_node_b );
+ ObjectTypeDB::bind_method( _MD("set_solver_priority","priority"), &Joint::set_solver_priority );
+ ObjectTypeDB::bind_method( _MD("get_solver_priority"), &Joint::get_solver_priority );
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_a"), _SCS("set_node_a"),_SCS("get_node_a") );
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_b"), _SCS("set_node_b"),_SCS("get_node_b") );
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "solver/priority",PROPERTY_HINT_RANGE,"1,8,1"), _SCS("set_solver_priority"),_SCS("get_solver_priority") );
+
}
@@ -148,7 +167,7 @@ void Joint::_bind_methods() {
Joint::Joint() {
-
+ solver_priority=1;
}
diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h
index 6daa06da2b..32bec1bd6f 100644
--- a/scene/3d/physics_joint.h
+++ b/scene/3d/physics_joint.h
@@ -44,6 +44,8 @@ class Joint : public Spatial {
NodePath a;
NodePath b;
+ int solver_priority;
+
protected:
@@ -62,6 +64,9 @@ public:
void set_node_b(const NodePath& p_node_b);
NodePath get_node_b() const;
+ void set_solver_priority(int p_priority);
+ int get_solver_priority() const;
+
RID get_joint() const { return joint; }
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..a5b009823c 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()) {
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 7036ef63ca..49ecf5779b 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,
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 07abd1dcd2..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;
@@ -179,7 +179,7 @@ void VehicleWheel::set_damping_compression(float p_value){
}
float VehicleWheel::get_damping_compression() const{
- return m_wheelsDampingRelaxation;
+ return m_wheelsDampingCompression;
}
void VehicleWheel::set_damping_relaxation(float p_value){
@@ -745,11 +745,12 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
{
if (engine_force != 0.f)
{
- rollingFriction = engine_force* s->get_step();
+ rollingFriction = -engine_force* s->get_step();
} else
{
real_t defaultRollingFrictionImpulse = 0.f;
- real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
+ float cbrake = MAX(wheelInfo.m_brake,brake);
+ real_t maxImpulse = cbrake ? cbrake : defaultRollingFrictionImpulse;
btVehicleWheelContactPoint contactPt(s,wheelInfo.m_raycastInfo.m_groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
rollingFriction = _calc_rolling_friction(contactPt);
}
@@ -1009,9 +1010,9 @@ void VehicleBody::_bind_methods(){
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_brake"),_SCS("get_brake"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_steering"),_SCS("get_steering"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.00,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_brake"),_SCS("get_brake"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"-180,180.0,0.01"),_SCS("set_steering"),_SCS("get_steering"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
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..a82c69e67f 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");
@@ -351,13 +359,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..e9fefe1ba0 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:
diff --git a/scene/SCsub b/scene/SCsub
index 28fb358106..8c4f0499c4 100644
--- a/scene/SCsub
+++ b/scene/SCsub
@@ -15,7 +15,7 @@ SConscript('resources/SCsub');
SConscript('io/SCsub');
-lib = env.Library("scene",env.scene_sources, LIBSUFFIX=env['platform_libsuffix'])
+lib = env.Library("scene",env.scene_sources)
env.Prepend(LIBS=[lib])
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 030f3f27e0..f9d36138a2 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -180,12 +180,16 @@ void AnimationPlayer::_get_property_list( List<PropertyInfo> *p_list) const {
}
+void AnimationPlayer::advance(float p_time) {
+
+ _animation_process( p_time );
+}
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
@@ -198,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;
@@ -217,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();
@@ -257,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;
@@ -344,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++) {
@@ -370,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)
@@ -918,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);
}
}
@@ -1174,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() {
@@ -1227,6 +1244,8 @@ void AnimationPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_current_animation_pos"),&AnimationPlayer::get_current_animation_pos);
ObjectTypeDB::bind_method(_MD("get_current_animation_length"),&AnimationPlayer::get_current_animation_length);
+ ObjectTypeDB::bind_method(_MD("advance","delta"),&AnimationPlayer::advance);
+
ADD_PROPERTY( PropertyInfo( Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode"));
ADD_PROPERTY( PropertyInfo( Variant::REAL, "playback/default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), _SCS("set_default_blend_time"), _SCS("get_default_blend_time"));
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 51c000d4d8..8ac5d96bf3 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -283,10 +283,15 @@ public:
float get_current_animation_pos() const;
float get_current_animation_length() const;
+ void advance(float p_time);
+
void set_root(const NodePath& p_root);
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..f668e52590 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,34 @@ 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","args"),&Tween::interpolate_callback, 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 +183,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 +215,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 +266,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 +416,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 +459,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 +484,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;
@@ -523,6 +531,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 +607,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 +625,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 +640,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 +665,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 +699,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 +728,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 +737,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 +768,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 +782,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 +797,7 @@ real_t Tween::get_runtime() const {
if(t > runtime)
runtime = t;
}
+ pending_update --;
return runtime;
}
@@ -779,6 +808,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 +908,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 +917,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 +930,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 +939,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 +955,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 +964,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 +984,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,16 +1000,17 @@ bool Tween::interpolate_method(Node *p_node
return true;
}
-bool Tween::interpolate_callback(Node *p_node
- , String p_callback
+bool Tween::interpolate_callback(Object *p_object
, real_t p_times_in_sec
+ , String p_callback
, Variant p_arg
) {
- 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;
@@ -980,30 +1018,33 @@ bool Tween::interpolate_callback(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_callback;
data.times_in_sec = p_times_in_sec;
data.delay = 0;
data.arg = p_arg;
+ 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 +1052,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 +1069,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 +1083,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 +1121,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 +1135,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 +1145,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 +1157,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 +1174,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 +1193,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 +1203,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 +1231,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 +1257,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..3e23cc362a 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:
@@ -82,12 +84,12 @@ private:
InterpolateType type;
bool finish;
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;
@@ -102,6 +104,7 @@ private:
bool active;
bool repeat;
float speed_scale;
+ mutable int pending_update;
List<InterpolateData> interpolates;
@@ -142,20 +145,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 +168,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 +178,16 @@ public:
, real_t p_delay = 0
);
- bool interpolate_callback(Node *p_node
- , String p_callback
+ bool interpolate_callback(Object *p_node
, real_t p_times_in_sec
+ , String p_callback
, Variant p_arg = Variant()
);
- 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 +195,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 +206,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 +217,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 6bad94bf0e..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
@@ -280,8 +280,8 @@ float EventPlayer::get_channel_last_note_time(int p_channel) const {
void EventPlayer::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&EventPlayer::set_stream);
- ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&EventPlayer::get_stream);
+ ObjectTypeDB::bind_method(_MD("set_stream","stream:EventStream"),&EventPlayer::set_stream);
+ ObjectTypeDB::bind_method(_MD("get_stream:EventStream"),&EventPlayer::get_stream);
ObjectTypeDB::bind_method(_MD("play"),&EventPlayer::play);
ObjectTypeDB::bind_method(_MD("stop"),&EventPlayer::stop);
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..0167687621 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);
@@ -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,24 @@ 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, "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 65cfd03505..94cc0a8d51 100644
--- a/scene/gui/button_group.cpp
+++ b/scene/gui/button_group.cpp
@@ -67,6 +67,9 @@ Array ButtonGroup::_get_button_list() const {
List<BaseButton*> b;
get_button_list(&b);
+
+ b.sort_custom<Node::Comparator>();
+
Array arr;
arr.resize(b.size());
@@ -114,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/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..ce268843b1 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) {
@@ -963,8 +963,8 @@ void Control::_window_input_event(InputEvent p_event) {
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();
+ 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
}
@@ -1034,8 +1034,8 @@ void Control::_window_input_event(InputEvent p_event) {
_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();
} else {
@@ -1079,8 +1079,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 +1126,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 +1148,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 +1204,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 +1231,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 +1291,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 +1306,7 @@ Control *Control::get_window() const {
bool Control::is_window() const {
- return (is_inside_scene() && window);
+ return (is_inside_tree() && window);
}
@@ -1325,9 +1326,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 +1357,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 +1384,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 +1415,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 +1444,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 +1476,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 +1505,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 +1535,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 +1565,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 +1594,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 +1626,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 +1643,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 +1696,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 +1767,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 +1999,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 +2197,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 +2207,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 +2221,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 +2236,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);
@@ -2249,6 +2268,7 @@ void Control::_window_sort_subwindows() {
return;
window->modal_stack.sort_custom<CComparator>();
+ window->subwindows.sort_custom<CComparator>();
window->subwindow_order_dirty=false;
}
@@ -2282,7 +2302,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 +2352,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 +2605,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 +2640,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 +2683,9 @@ 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::_bind_methods() {
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index ac0ded03ab..a82cfc7ea6 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);
diff --git a/scene/gui/empty_control.cpp b/scene/gui/empty_control.cpp
deleted file mode 100644
index 1e377b2b73..0000000000
--- a/scene/gui/empty_control.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*************************************************************************/
-/* empty_control.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 "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()
-{
-}
diff --git a/scene/gui/empty_control.h b/scene/gui/empty_control.h
deleted file mode 100644
index 993af45ac4..0000000000
--- a/scene/gui/empty_control.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************************************/
-/* empty_control.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 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
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 b7918994d8..d2e1e7f0b9 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -339,7 +339,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();
@@ -397,6 +397,7 @@ void Label::regenerate_word_cache() {
}
+
if (current=='\n') {
insert_newline=true;
} else {
@@ -446,7 +447,7 @@ void Label::regenerate_word_cache() {
}
- total_char_cache -= line_count + 1; // do not count new lines (including the first one)
+ //total_char_cache -= line_count + 1; // do not count new lines (including the first one)
if (!autowrap) {
@@ -535,7 +536,7 @@ void Label::set_percent_visible(float p_percent) {
if (p_percent<0)
set_visible_characters(-1);
else
- set_visible_characters(get_total_character_count()*p_percent);
+ set_visible_characters(get_total_character_count()*p_percent);
percent_visible=p_percent;
}
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..bccd05d4fe 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
}
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..c2e988de95 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);
@@ -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..8855627bb4 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,188 @@ 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];
+ 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];
+ 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 +601,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 +793,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 +814,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 +954,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 +982,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 +996,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 +1034,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 +1126,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 +1137,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-=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+=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 +1412,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 +1465,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 +1493,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 +1507,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 +1516,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 +1546,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 +1570,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 +1604,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 +1804,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 +1861,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 +2037,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 +2069,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 +2215,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 +2230,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 +2265,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 +2281,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 +2308,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 +2457,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 +2549,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 +2563,7 @@ void TextEdit::set_text(String p_text){
cursor_set_column(0);
update();
setting_text=false;
-
+
//get_range()->set(0);
};
@@ -2317,29 +2571,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 +2630,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 +2665,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 +2683,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 +2704,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 +2777,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 +2873,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 +2887,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 +2895,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 +2942,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 +2956,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 +2974,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 +3041,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 +3085,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 +3105,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 +3132,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 +3176,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 +3189,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 +3225,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 +3237,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 +3332,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 +3343,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 +3525,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 +3561,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 +3603,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 +3628,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 9084983a4c..b7b52a39dc 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1438,8 +1438,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
if (p_button==BUTTON_LEFT) {
/* process selection */
- if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON)) {
-
+ if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON || c.mode==TreeItem::CELL_MODE_CHECK)) {
emit_signal("item_activated");
return -1;
@@ -1500,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;
}
@@ -1576,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;
}
@@ -1694,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(); }
@@ -2344,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) {
@@ -2354,7 +2360,7 @@ void Tree::_notification(int p_what) {
}
}
- if (p_what==NOTIFICATION_ENTER_SCENE) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
update_cache();;
}
@@ -2812,7 +2818,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/io/scene_format_object.cpp b/scene/io/scene_format_object.cpp
deleted file mode 100644
index 6ffae30282..0000000000
--- a/scene/io/scene_format_object.cpp
+++ /dev/null
@@ -1,851 +0,0 @@
-/*************************************************************************/
-/* scene_format_object.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 "scene_format_object.h"
-#include "print_string.h"
-#include "globals.h"
-#include "scene/resources/packed_scene.h"
-#include "io/resource_loader.h"
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-void SceneFormatSaverObject::save_node(const Node* p_root,const Node* p_node,const Node* p_owner,ObjectFormatSaver *p_saver,String p_base_path,uint32_t p_flags,Map<const Node*,uint32_t>& owner_id) const {
-
- if (p_node!=p_root && p_node->get_owner()==NULL)
- return;
-
-
- if (p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES || p_node->get_owner() == p_owner || p_node == p_owner ) {
-
- Dictionary d;
- if (p_root!=p_node) {
- d["path"]=p_root->get_path_to(p_node->get_parent());
- }
-
- d["name"]=p_node->get_name();
-
- /* Connections */
-
- List<MethodInfo> signal_list;
-
- p_node->get_signal_list(&signal_list);
-
- int conn_count=0;
-
- Set<Node::Connection> exclude_connections;
-
- if (!(p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES)) {
-
- Vector<Node::Connection> ex = p_node->get_instance_connections();
- for(int i=0;i<ex.size();i++) {
- exclude_connections.insert(ex[i]);
- }
- }
-
- for (List<MethodInfo>::Element *S=signal_list.front();S;S=S->next()) {
-
- List<Node::Connection> connections;
- p_node->get_signal_connection_list(S->get().name,&connections);
- for(List<Node::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- Node::Connection &c=E->get();
- if (!(c.flags&Object::CONNECT_PERSIST))
- continue;
- if (exclude_connections.has(c))
- continue;
-
- Node *target = c.target->cast_to<Node>();
- if (!target)
- continue; //connected to something not a node, ignoring
-
- Dictionary cd;
- cd["signal"]=c.signal;
- cd["target"]=p_node->get_path_to(target);
- cd["method"]=c.method;
- cd["realtime"]=!(c.flags&Object::CONNECT_DEFERRED);
- if (c.binds.size())
- cd["binds"]=c.binds;
- d["connection/"+itos(conn_count+1)]=cd;
-
- conn_count++;
- }
- }
-
- d["connection_count"]=conn_count;
- if (owner_id.has(p_node->get_owner())) {
-
- d["owner"]=owner_id[p_node->get_owner()];
- }
-
- /* Groups */
-
- DVector<String> group_array;
- List<Node::GroupInfo> groups;
- p_node->get_groups(&groups);
- Set<StringName> exclude_groups;
-
- if (!(p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES)) {
- //generate groups to exclude (came from instance)
- Vector<StringName> eg;
- eg=p_node->get_instance_groups();
- for(int i=0;i<eg.size();i++)
- exclude_groups.insert(eg[i]);
- }
-
- for(List<Node::GroupInfo>::Element*E=groups.front();E;E=E->next()) {
-
- if (E->get().persistent && !exclude_groups.has(E->get().name))
- group_array.push_back(E->get().name);
- }
-
- if (group_array.size())
- d["groups"]=group_array;
-
- /* Save */
-
- if (p_owner!=p_node && p_node->get_filename()!="") {
-
- String instance_path;
- if (p_flags&SceneSaver::FLAG_RELATIVE_PATHS)
- instance_path=p_base_path.path_to_file(Globals::get_singleton()->localize_path(p_node->get_filename()));
- else
- instance_path=p_node->get_filename();
- d["instance"]=instance_path;
-
- if (p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES) {
-
- int id = owner_id.size();
- d["owner_id"]=id;
- owner_id[p_node]=id;
-
- p_saver->save(p_node,d);
-
- //owner change!
- for (int i=0;i<p_node->get_child_count();i++) {
-
- save_node(p_root,p_node->get_child(i),p_node,p_saver,p_base_path,p_flags,owner_id);
- }
- return;
-
- } else {
- DVector<String> prop_names;
- Array prop_values;
-
- List<PropertyInfo> properties;
- p_node->get_property_list(&properties);
-
- //instance state makes sure that only changes to instance are saved
- Dictionary instance_state=p_node->get_instance_state();
-
- for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
-
- if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
- continue;
-
- String name=E->get().name;
- Variant value=p_node->get(E->get().name);
-
- if (!instance_state.has(name))
- continue; // did not change since it was loaded, not save
- if (value==instance_state[name])
- continue;
- prop_names.push_back( name );
- prop_values.push_back( value );
-
- }
-
- d["override_names"]=prop_names;
- d["override_values"]=prop_values;
-
- p_saver->save(NULL,d);
- }
- } else {
-
- p_saver->save(p_node,d);
- }
- }
-
- for (int i=0;i<p_node->get_child_count();i++) {
-
- save_node(p_root,p_node->get_child(i),p_owner,p_saver,p_base_path,p_flags,owner_id);
- }
-}
-
-
-Error SceneFormatSaverObject::save(const String &p_path,const Node* p_scene,uint32_t p_flags,const Ref<OptimizedSaver> &p_optimizer) {
-
- String extension=p_path.extension();
- if (extension=="scn")
- extension="bin";
- if (extension=="xscn")
- extension="xml";
-
- String local_path=Globals::get_singleton()->localize_path(p_path);
- uint32_t saver_flags=0;
- if (p_flags&SceneSaver::FLAG_RELATIVE_PATHS)
- saver_flags|=ObjectSaver::FLAG_RELATIVE_PATHS;
- if (p_flags&SceneSaver::FLAG_BUNDLE_RESOURCES)
- saver_flags|=ObjectSaver::FLAG_BUNDLE_RESOURCES;
- if (p_flags&SceneSaver::FLAG_OMIT_EDITOR_PROPERTIES)
- saver_flags|=ObjectSaver::FLAG_OMIT_EDITOR_PROPERTIES;
- if (p_flags&SceneSaver::FLAG_SAVE_BIG_ENDIAN)
- saver_flags|=ObjectSaver::FLAG_SAVE_BIG_ENDIAN;
-
- ObjectFormatSaver *saver = ObjectSaver::instance_format_saver(local_path,"SCENE",extension,saver_flags,p_optimizer);
-
- ERR_FAIL_COND_V(!saver,ERR_FILE_UNRECOGNIZED);
-
- /* SAVE SCENE */
-
- Map<const Node*,uint32_t> node_id_map;
- save_node(p_scene,p_scene,p_scene,saver,local_path,p_flags,node_id_map);
-
- memdelete(saver);
-
- return OK;
-}
-
-void SceneFormatSaverObject::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("xml");
- p_extensions->push_back("scn");
- p_extensions->push_back("xscn");
-
-// ObjectSaver::get_recognized_extensions(p_extensions);
-}
-
-
-/////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////
-
-void SceneFormatLoaderObject::_apply_meta(Node *node, const Variant&meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map) {
-
- r_err = OK;
-
-
- Dictionary d=meta;
-
- if (!d.has("name")) {
-
- r_err=ERR_WTF;
- memdelete(node);
- ERR_FAIL_COND(!d.has("name"));
- }
-
-
- node->set_name(d["name"]);
- int connection_count=d.has("connection_count")?d["connection_count"].operator int():0;
-
-
- for (int i=0;i<connection_count;i++) {
-
- Dictionary cd=d["connection/"+itos(i+1)];
-
- ERR_CONTINUE(!cd.has("target"));
- ERR_CONTINUE(!cd.has("method"));
- ERR_CONTINUE(!cd.has("realtime"));
- ERR_CONTINUE(!cd.has("signal"));
-
- ConnectionItem ci;
-
- ci.node=node;
- ci.target=cd["target"];
- ci.method=cd["method"];
- ci.signal=cd["signal"];
- ci.realtime=cd["realtime"];
- if (cd.has("binds"))
- ci.binds=cd["binds"];
-
- connections.push_back(ci);
-
- }
-
- DVector<String> groups=d.has("groups")?d["groups"].operator DVector<String>():DVector<String>();
- for (int i=0;i<groups.size();i++) {
-
- node->add_to_group(groups[i],true);
- }
-
-}
-
-
-
-Ref<SceneInteractiveLoader> SceneFormatLoaderObject::load_interactive(const String &p_path,bool p_save_root_state) {
-
- SceneInteractiveLoaderObject *sil = memnew( SceneInteractiveLoaderObject(p_path,p_save_root_state) );
-
- if (sil->error!=OK) {
-
- memdelete( sil );
- return Ref<SceneInteractiveLoader>();
- }
-
- return Ref<SceneInteractiveLoader>( sil );
-
-}
-
-
-Node* SceneFormatLoaderObject::load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_save_instance_state,Map<uint32_t,Node*>& owner_map) {
-
- r_err = OK;
-
- Node *node=obj->cast_to<Node>();
-
- _apply_meta(node,meta,p_loader,connections,r_err,owner_map);
- if (r_err!=OK)
- return NULL;
-
- Dictionary d=meta;
-
- if (p_root) {
- NodePath path=d.has("path")?d["path"].operator NodePath():NodePath(".");
-
- Node *parent=p_root->get_node(path);
- if (!parent) {
- memdelete(node);
- r_err=ERR_FILE_CORRUPT;
- ERR_FAIL_COND_V(!parent,NULL);
- }
-
- parent->add_child(node);
-
- if (d.has("owner_id")) {
- //is owner
- owner_map[d["owner_id"]]=node;
- if (d.has("instance"))
- node->set_filename(d["instance"]);
-
- }
-
- if (d.has("owner")) {
-
- uint32_t owner = d["owner"];
- ERR_FAIL_COND_V(!owner_map.has(owner),NULL);
- node->set_owner(owner_map[owner]);
- } else {
-
- node->set_owner(p_root);
- }
- }
-
- return node;
-}
-
-void SceneFormatLoaderObject::_apply_connections(List<ConnectionItem>& connections) {
-
- int idx=0;
- for (List<ConnectionItem>::Element *E=connections.front();E;E=E->next()) {
-
- ConnectionItem &ci=E->get();
- Node *target = ci.node->get_node(ci.target);
- ERR_CONTINUE(!target);
- ci.node->connect(ci.signal,target,ci.method,ci.binds,(ci.realtime?0:Object::CONNECT_DEFERRED)|Object::CONNECT_PERSIST);
- idx++;
- }
-
-}
-
-Node* SceneFormatLoaderObject::load(const String &p_path,bool p_save_instance_state) {
-
- List<ConnectionItem> connections;
-
- String extension=p_path.extension();
- if (extension=="scn")
- extension="bin";
- if (extension=="xscn")
- extension="xml";
-
- String local_path = Globals::get_singleton()->localize_path(p_path);
-
- ObjectFormatLoader *loader = ObjectLoader::instance_format_loader(local_path,"SCENE",extension);
-
- ERR_EXPLAIN("Couldn't load scene: "+p_path);
- ERR_FAIL_COND_V(!loader,NULL);
-
- Node *root=NULL;
- Map<uint32_t,Node*> owner_map;
-
- while(true) {
-
- Object *obj=NULL;
- Variant metav;
- Error r_err=loader->load(&obj,metav);
-
- if (r_err == ERR_SKIP) {
- continue;
- };
-
- if (r_err==ERR_FILE_EOF) {
- memdelete(loader);
- ERR_FAIL_COND_V(!root,NULL);
- _apply_connections(connections);
- return root;
- }
-
- if (r_err || (!obj && metav.get_type()==Variant::NIL)) {
- memdelete(loader);
- ERR_EXPLAIN("Object Loader Failed for Scene: "+p_path) ;
- ERR_FAIL_COND_V( r_err, NULL);
- ERR_EXPLAIN("Object Loader Failed for Scene: "+p_path) ;
- ERR_FAIL_COND_V( !obj && metav.get_type()==Variant::NIL,NULL);
- }
-
- if (obj) {
- if (obj->cast_to<Node>()) {
-
- Error err;
- Node* node = load_node(obj, metav, root, loader,connections,err,p_save_instance_state,owner_map);
- if (err)
- memdelete(loader);
-
- ERR_FAIL_COND_V( err, NULL );
- if (!root)
- root=node;
- } else {
-
- memdelete(loader);
- ERR_FAIL_V( NULL );
-
- }
- } else {
-
- // check for instance
- Dictionary meta=metav;
- if (meta.has("instance")) {
- if (!root) {
-
- memdelete(loader);
- ERR_FAIL_COND_V(!root,NULL);
- }
-
- String path = meta["instance"];
-
- if (path.find("://")==-1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- path=Globals::get_singleton()->localize_path(
- local_path.get_base_dir()+"/"+path);
- }
-
-
- Node *scene = SceneLoader::load(path);
-
- if (!scene) {
-
- Ref<PackedScene> sd = ResourceLoader::load(path);
- if (sd.is_valid()) {
-
- scene=sd->instance();
- }
- }
-
-
- if (!scene) {
-
- memdelete(loader);
- ERR_FAIL_COND_V(!scene,NULL);
- }
-
- if (p_save_instance_state)
- scene->generate_instance_state();
-
-
- Error err;
- _apply_meta(scene,metav,loader,connections,err,owner_map);
- if (err!=OK) {
- memdelete(loader);
- ERR_FAIL_COND_V(err!=OK,NULL);
- }
-
- Node *parent=root;
-
- if (meta.has("path"))
- parent=root->get_node(meta["path"]);
-
-
- if (!parent) {
-
- memdelete(loader);
- ERR_FAIL_COND_V(!parent,NULL);
- }
-
-
- if (meta.has("override_names") && meta.has("override_values")) {
-
- DVector<String> override_names=meta["override_names"];
- Array override_values=meta["override_values"];
-
- int len = override_names.size();
- if ( len > 0 && len == override_values.size() ) {
-
- DVector<String>::Read names = override_names.read();
-
- for(int i=0;i<len;i++) {
-
- scene->set(names[i],override_values[i]);
- }
-
- }
-
- }
-
- scene->set_filename(path);
-
- parent->add_child(scene);
- scene->set_owner(root);
- }
- }
- }
-
- return NULL;
-}
-
-void SceneFormatLoaderObject::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("xml");
- p_extensions->push_back("scn");
- p_extensions->push_back("xscn");
-
-// ObjectLoader::get_recognized_extensions(p_extensions);
-
-}
-
-
-
-///////////////////////////////////////////////////
-
-
-void SceneInteractiveLoaderObject::_apply_meta(Node *node, const Variant&meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map) {
-
- r_err = OK;
-
-
- Dictionary d=meta;
-
- if (!d.has("name")) {
-
- r_err=ERR_WTF;
- memdelete(node);
- ERR_FAIL_COND(!d.has("name"));
- }
-
-
- node->set_name(d["name"]);
- int connection_count=d.has("connection_count")?d["connection_count"].operator int():0;
-
-
- for (int i=0;i<connection_count;i++) {
-
- Dictionary cd=d["connection/"+itos(i+1)];
-
- ERR_CONTINUE(!cd.has("target"));
- ERR_CONTINUE(!cd.has("method"));
- ERR_CONTINUE(!cd.has("realtime"));
- ERR_CONTINUE(!cd.has("signal"));
-
- ConnectionItem ci;
-
- ci.node=node;
- ci.target=cd["target"];
- ci.method=cd["method"];
- ci.signal=cd["signal"];
- ci.realtime=cd["realtime"];
- if (cd.has("binds"))
- ci.binds=cd["binds"];
-
- connections.push_back(ci);
-
- }
-
- DVector<String> groups=d.has("groups")?d["groups"].operator DVector<String>():DVector<String>();
- for (int i=0;i<groups.size();i++) {
-
- node->add_to_group(groups[i],true);
- }
-
-}
-
-
-
-Node* SceneInteractiveLoaderObject::load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_save_instance_state,Map<uint32_t,Node*>& owner_map) {
-
- r_err = OK;
-
- Node *node=obj->cast_to<Node>();
-
- _apply_meta(node,meta,p_loader,connections,r_err,owner_map);
- if (r_err!=OK)
- return NULL;
-
- Dictionary d=meta;
-
- if (p_root) {
- NodePath path=d.has("path")?d["path"].operator NodePath():NodePath(".");
-
- Node *parent=p_root->get_node(path);
- if (!parent) {
- memdelete(node);
- r_err=ERR_FILE_CORRUPT;
- ERR_FAIL_COND_V(!parent,NULL);
- }
-
- parent->add_child(node);
-
- if (d.has("owner_id")) {
- //is owner
- owner_map[d["owner_id"]]=node;
- if (d.has("instance"))
- node->set_filename(d["instance"]);
-
- }
-
- if (d.has("owner")) {
-
- uint32_t owner = d["owner"];
- ERR_FAIL_COND_V(!owner_map.has(owner),NULL);
- node->set_owner(owner_map[owner]);
- } else {
-
- node->set_owner(p_root);
- }
- }
-
- return node;
-}
-
-void SceneInteractiveLoaderObject::_apply_connections(List<ConnectionItem>& connections) {
-
- int idx=0;
- for (List<ConnectionItem>::Element *E=connections.front();E;E=E->next()) {
-
- ConnectionItem &ci=E->get();
- Node *target = ci.node->get_node(ci.target);
- ERR_CONTINUE(!target);
- ci.node->connect(ci.signal,target,ci.method,ci.binds,(ci.realtime?0:Object::CONNECT_DEFERRED)|Object::CONNECT_PERSIST);
- idx++;
- }
-
-}
-
-SceneInteractiveLoaderObject::SceneInteractiveLoaderObject(const String &p_path,bool p_save_root_state) {
-
- error=OK;
- path=p_path;
- save_instance_state=p_save_root_state;
- node_path=p_path;
- root=NULL;
- stage_max=1;
- stage=0;
-
-
- String extension=p_path.extension();
- if (extension=="scn")
- extension="bin";
- if (extension=="xscn")
- extension="xml";
-
- local_path = Globals::get_singleton()->localize_path(p_path);
-
- loader = ObjectLoader::instance_format_loader(local_path,"SCENE",extension);
-
- if (!loader) {
-
- error=ERR_CANT_OPEN;
- }
- ERR_EXPLAIN("Couldn't load scene: "+p_path);
- ERR_FAIL_COND(!loader);
-
-}
-
-
-
-void SceneInteractiveLoaderObject::set_local_path(const String& p_local_path) {
-
- node_path=p_local_path;
-}
-
-Node *SceneInteractiveLoaderObject::get_scene() {
-
- if (error==ERR_FILE_EOF)
- return root;
- return NULL;
-}
-Error SceneInteractiveLoaderObject::poll() {
-
- if (error!=OK)
- return error;
-
- Object *obj=NULL;
- Variant metav;
- Error r_err=loader->load(&obj,metav);
-
-
- if (r_err == ERR_SKIP) {
- stage++;
- return OK;
- };
-
- if (r_err==ERR_FILE_EOF) {
- memdelete(loader);
- error=ERR_FILE_CORRUPT;
- ERR_FAIL_COND_V(!root,ERR_FILE_CORRUPT);
- _apply_connections(connections);
- error=ERR_FILE_EOF;
- if (root)
- root->set_filename(node_path);
- return error;
- }
-
- if (r_err || (!obj && metav.get_type()==Variant::NIL)) {
- memdelete(loader);
- error=ERR_FILE_CORRUPT;
- ERR_EXPLAIN("Object Loader Failed for Scene: "+path);
- ERR_FAIL_COND_V( r_err, ERR_FILE_CORRUPT);
- ERR_EXPLAIN("Object Loader Failed for Scene: "+path);
- ERR_FAIL_COND_V( !obj && metav.get_type()==Variant::NIL,ERR_FILE_CORRUPT);
- }
-
- if (obj) {
- if (obj->cast_to<Node>()) {
-
- Error err;
- Node* node = load_node(obj, metav, root, loader,connections,err,save_instance_state,owner_map);
- if (err) {
- error=ERR_FILE_CORRUPT;
- memdelete(loader);
- }
-
- ERR_FAIL_COND_V( err, ERR_FILE_CORRUPT );
- if (!root)
- root=node;
- } else {
-
- error=ERR_FILE_CORRUPT;
- memdelete(loader);
- ERR_EXPLAIN("Loaded something not a node.. (?)");
- ERR_FAIL_V( ERR_FILE_CORRUPT );
-
- }
- } else {
-
- // check for instance
- Dictionary meta=metav;
- if (meta.has("instance")) {
-
- if (!root) {
-
- error=ERR_FILE_CORRUPT;
- memdelete(loader);
- ERR_FAIL_COND_V(!root,ERR_FILE_CORRUPT);
- }
-
- String path = meta["instance"];
-
- if (path.find("://")==-1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- path=Globals::get_singleton()->localize_path(
- local_path.get_base_dir()+"/"+path);
- }
-
- Node *scene = SceneLoader::load(path);
-
- if (!scene) {
-
- error=ERR_FILE_CORRUPT;
- memdelete(loader);
- ERR_FAIL_COND_V(!scene,ERR_FILE_CORRUPT);
- }
-
- if (save_instance_state)
- scene->generate_instance_state();
-
-
- Error err;
- _apply_meta(scene,metav,loader,connections,err,owner_map);
- if (err!=OK) {
- error=ERR_FILE_CORRUPT;
- memdelete(loader);
- ERR_FAIL_COND_V(err!=OK,ERR_FILE_CORRUPT);
- }
-
- Node *parent=root;
-
- if (meta.has("path"))
- parent=root->get_node(meta["path"]);
-
-
- if (!parent) {
-
- error=ERR_FILE_CORRUPT;
- memdelete(loader);
- ERR_FAIL_COND_V(!parent,ERR_FILE_CORRUPT);
- }
-
-
- if (meta.has("override_names") && meta.has("override_values")) {
-
- DVector<String> override_names=meta["override_names"];
- Array override_values=meta["override_values"];
-
- int len = override_names.size();
- if ( len > 0 && len == override_values.size() ) {
-
- DVector<String>::Read names = override_names.read();
-
- for(int i=0;i<len;i++) {
-
- scene->set(names[i],override_values[i]);
- }
-
- }
-
- }
-
- scene->set_filename(path);
-
- parent->add_child(scene);
- scene->set_owner(root);
- }
- }
-
- stage++;
- error=OK;
- return error;
-
-}
-int SceneInteractiveLoaderObject::get_stage() const {
-
- return stage;
-}
-int SceneInteractiveLoaderObject::get_stage_count() const {
-
- return stage_max;
-}
-
-
-#endif
diff --git a/scene/io/scene_format_object.h b/scene/io/scene_format_object.h
deleted file mode 100644
index 3f0bbd4627..0000000000
--- a/scene/io/scene_format_object.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*************************************************************************/
-/* scene_format_object.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 SCENE_FORMAT_OBJECT_H
-#define SCENE_FORMAT_OBJECT_H
-
-
-#include "scene/main/node.h"
-#include "scene/io/scene_saver.h"
-#include "scene/io/scene_loader.h"
-#include "io/object_saver.h"
-#include "io/object_loader.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-class SceneFormatSaverObject : public SceneFormatSaver {
-
- void save_node(const Node* p_root,const Node* p_node,const Node* p_owner,ObjectFormatSaver *p_saver,String p_base_path,uint32_t p_flags,Map<const Node*,uint32_t>& owner_id) const;
-
-public:
-
- virtual Error save(const String &p_path,const Node* p_scenezz,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>());
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual ~SceneFormatSaverObject() {}
-};
-
-
-
-class SceneFormatLoaderObject : public SceneFormatLoader {
-
-
- struct ConnectionItem {
- Node *node;
- NodePath target;
- StringName method;
- StringName signal;
- Vector<Variant> binds;
- bool realtime;
- };
-
- Node* load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_root_scene_hint,Map<uint32_t,Node*>& owner_map);
- void _apply_connections(List<ConnectionItem>& connections);
- void _apply_meta(Node *node, const Variant& meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map);
-
-public:
-
- virtual Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_root_scene_hint=false);
- virtual Node* load(const String &p_path,bool p_save_root_state=false);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
-};
-
-
-class SceneInteractiveLoaderObject : public SceneInteractiveLoader {
-
- OBJ_TYPE(SceneInteractiveLoaderObject,SceneInteractiveLoader);
-
- struct ConnectionItem {
- Node *node;
- NodePath target;
- StringName method;
- StringName signal;
- Vector<Variant> binds;
- bool realtime;
- };
- ObjectFormatLoader *loader;
- String path;
- String node_path;
- String local_path;
- Error error;
- bool save_instance_state;
- List<ConnectionItem> connections;
- Map<uint32_t,Node*> owner_map;
- Node *root;
- int stage_max;
- int stage;
-
-
- Node* load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_root_scene_hint,Map<uint32_t,Node*>& owner_map);
- void _apply_connections(List<ConnectionItem>& connections);
- void _apply_meta(Node *node, const Variant& meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map);
-
-friend class SceneFormatLoaderObject;
-public:
-
- virtual void set_local_path(const String& p_local_path);
- virtual Node *get_scene();
- virtual Error poll();
- virtual int get_stage() const;
- virtual int get_stage_count() const;
-
-
- SceneInteractiveLoaderObject(const String &p_path,bool p_save_root_state=false);
-};
-
-
-
-#endif
-#endif
diff --git a/scene/io/scene_format_script.cpp b/scene/io/scene_format_script.cpp
deleted file mode 100644
index a6f1596d2b..0000000000
--- a/scene/io/scene_format_script.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*************************************************************************/
-/* scene_format_script.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 "scene_format_script.h"
-#if 0
-Node* SceneFormatLoaderScript::load(const String &p_path,bool p_save_instance_state) {
-
- Ref<Script> script = ResourceLoader::load(p_path);
- ERR_EXPLAIN("Can't load script-based scene: "+p_path);
- ERR_FAIL_COND_V(script.is_null(),NULL);
- ERR_EXPLAIN("Script does not instance in a node: "+p_path);
- ERR_FAIL_COND_V(script->get_node_type()=="",NULL);
- String node_type=script->get_node_type();
- Object *obj = ObjectTypeDB::instance(node_type);
- ERR_EXPLAIN("Unknown node type for instancing '"+node_type+"' in script: "+p_path);
- ERR_FAIL_COND_V(!obj,NULL);
- Node *node = obj->cast_to<Node>();
- if (!node)
- memdelete(obj);
- ERR_EXPLAIN("Node type '"+node_type+"' not of type 'Node'' in script: "+p_path);
- ERR_FAIL_COND_V(!node,NULL);
-
- node->set_script(script.get_ref_ptr());
-
- return node;
-}
-
-void SceneFormatLoaderScript::get_recognized_extensions(List<String> *p_extensions) const {
-
- for (int i=0;i<ScriptServer::get_language_count();i++) {
-
- ScriptServer::get_language(i)->get_recognized_extensions(p_extensions);
- }
-}
-
-
-SceneFormatLoaderScript::SceneFormatLoaderScript()
-{
-}
-#endif
diff --git a/scene/io/scene_format_script.h b/scene/io/scene_format_script.h
deleted file mode 100644
index 9bfcc0b1e3..0000000000
--- a/scene/io/scene_format_script.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************************************/
-/* scene_format_script.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 SCENE_FORMAT_SCRIPT_H
-#define SCENE_FORMAT_SCRIPT_H
-
-#include "scene/io/scene_loader.h"
-#include "io/resource_loader.h"
-#if 0
-
-class SceneFormatLoaderScript : public SceneFormatLoader {
-public:
-
- virtual Node* load(const String &p_path,bool p_save_instance_state=false);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
- SceneFormatLoaderScript();
-};
-#endif
-#endif // SCENE_FORMAT_SCRIPT_H
diff --git a/scene/io/scene_loader.cpp b/scene/io/scene_loader.cpp
deleted file mode 100644
index 8615e64ae9..0000000000
--- a/scene/io/scene_loader.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/*************************************************************************/
-/* scene_loader.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 "scene_loader.h"
-#include "globals.h"
-#include "path_remap.h"
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-SceneFormatLoader *SceneLoader::loader[MAX_LOADERS];
-
-int SceneLoader::loader_count=0;
-
-
-void SceneInteractiveLoader::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("get_scene"),&SceneInteractiveLoader::get_scene);
- ObjectTypeDB::bind_method(_MD("poll"),&SceneInteractiveLoader::poll);
- ObjectTypeDB::bind_method(_MD("get_stage"),&SceneInteractiveLoader::get_stage);
- ObjectTypeDB::bind_method(_MD("get_stage_count"),&SceneInteractiveLoader::get_stage_count);
-}
-
-class SceneInteractiveLoaderDefault : public SceneInteractiveLoader {
-
- OBJ_TYPE( SceneInteractiveLoaderDefault, SceneInteractiveLoader );
-public:
- Node *scene;
-
- virtual void set_local_path(const String& p_local_path) { scene->set_filename(p_local_path); }
- virtual Node *get_scene() { return scene; }
- virtual Error poll() { return ERR_FILE_EOF; }
- virtual int get_stage() const { return 1; }
- virtual int get_stage_count() const { return 1; }
-
- SceneInteractiveLoaderDefault() {}
-};
-
-
-Ref<SceneInteractiveLoader> SceneFormatLoader::load_interactive(const String &p_path,bool p_root_scene_hint) {
-
- Node *scene = load(p_path,p_root_scene_hint);
- if (!scene)
- return Ref<SceneInteractiveLoader>();
- Ref<SceneInteractiveLoaderDefault> sil = Ref<SceneInteractiveLoaderDefault>( memnew( SceneInteractiveLoaderDefault ));
- sil->scene=scene;
- return sil;
-}
-
-
-
-bool SceneFormatLoader::recognize(const String& p_extension) const {
-
-
- List<String> extensions;
- get_recognized_extensions(&extensions);
- for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- if (E->get().nocasecmp_to(p_extension.extension())==0)
- return true;
- }
-
- return false;
-}
-
-Ref<SceneInteractiveLoader> SceneLoader::load_interactive(const String &p_path,bool p_save_root_state) {
-
- String local_path=Globals::get_singleton()->localize_path(p_path);
-
- String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
- String extension=remapped_path.extension();
-
- for (int i=0;i<loader_count;i++) {
-
- if (!loader[i]->recognize(extension))
- continue;
- Ref<SceneInteractiveLoader> il = loader[i]->load_interactive(remapped_path,p_save_root_state);
-
- if (il.is_null() && remapped_path!=local_path)
- il = loader[i]->load_interactive(local_path,p_save_root_state);
-
- ERR_EXPLAIN("Error loading scene: "+local_path);
- ERR_FAIL_COND_V(il.is_null(),Ref<SceneInteractiveLoader>());
- il->set_local_path(local_path);
-
- return il;
- }
-
- ERR_EXPLAIN("No loader found for scene: "+p_path);
- ERR_FAIL_V(Ref<SceneInteractiveLoader>());
- return Ref<SceneInteractiveLoader>();
-}
-
-Node* SceneLoader::load(const String &p_path,bool p_root_scene_hint) {
-
- String local_path=Globals::get_singleton()->localize_path(p_path);
-
- String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
- String extension=remapped_path.extension();
-
- for (int i=0;i<loader_count;i++) {
-
- if (!loader[i]->recognize(extension))
- continue;
- Node*node = loader[i]->load(remapped_path,p_root_scene_hint);
-
- if (!node && remapped_path!=local_path)
- node = loader[i]->load(local_path,p_root_scene_hint);
-
- ERR_EXPLAIN("Error loading scene: "+local_path);
- ERR_FAIL_COND_V(!node,NULL);
- node->set_filename(local_path);
-
- return node;
- }
-
- ERR_EXPLAIN("No loader found for scene: "+p_path);
- ERR_FAIL_V(NULL);
-}
-
-void SceneLoader::get_recognized_extensions(List<String> *p_extensions) {
-
- for (int i=0;i<loader_count;i++) {
-
- loader[i]->get_recognized_extensions(p_extensions);
- }
-
-}
-
-void SceneLoader::add_scene_format_loader(SceneFormatLoader *p_format_loader) {
-
- ERR_FAIL_COND( loader_count >= MAX_LOADERS );
- loader[loader_count++]=p_format_loader;
-}
-
-
-#endif
diff --git a/scene/io/scene_loader.h b/scene/io/scene_loader.h
deleted file mode 100644
index 2562fc0520..0000000000
--- a/scene/io/scene_loader.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*************************************************************************/
-/* scene_loader.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 SCENE_LOADER_H
-#define SCENE_LOADER_H
-
-#include "scene/main/node.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-class SceneInteractiveLoader : public Reference {
-
- OBJ_TYPE(SceneInteractiveLoader,Reference);
-protected:
-
- static void _bind_methods();
-public:
-
- virtual void set_local_path(const String& p_local_path)=0;
- virtual Node *get_scene()=0;
- virtual Error poll()=0;
- virtual int get_stage() const=0;
- virtual int get_stage_count() const=0;
-
-
- SceneInteractiveLoader() {}
-};
-
-class SceneFormatLoader {
-public:
-
- virtual Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_root_scene_hint=false);
- virtual Node* load(const String &p_path,bool p_root_scene_hint=false)=0;
- virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
- bool recognize(const String& p_extension) const;
-
- virtual ~SceneFormatLoader() {}
-};
-
-class SceneLoader {
-
- enum {
- MAX_LOADERS=64
- };
-
- static SceneFormatLoader *loader[MAX_LOADERS];
- static int loader_count;
-
-public:
-
- static Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_save_root_state=false);
- static Node* load(const String &p_path,bool p_save_root_state=false);
- static void add_scene_format_loader(SceneFormatLoader *p_format_loader);
- static void get_recognized_extensions(List<String> *p_extensions);
-
-
-};
-
-#endif
-
-#endif
diff --git a/scene/io/scene_saver.cpp b/scene/io/scene_saver.cpp
deleted file mode 100644
index f1b503ef27..0000000000
--- a/scene/io/scene_saver.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*************************************************************************/
-/* scene_saver.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 "scene_saver.h"
-#include "print_string.h"
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-SceneFormatSaver *SceneSaver::saver[MAX_SAVERS];
-
-int SceneSaver::saver_count=0;
-
-bool SceneFormatSaver::recognize(const String& p_extension) const {
-
-
- List<String> extensions;
- get_recognized_extensions(&extensions);
- for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
-
- if (E->get().nocasecmp_to(p_extension.extension())==0)
- return true;
- }
-
- return false;
-}
-
-Error SceneSaver::save(const String &p_path,const Node* p_scene,uint32_t p_flags,const Ref<OptimizedSaver> &p_optimizer) {
-
- String extension=p_path.extension();
- Error err=ERR_FILE_UNRECOGNIZED;
- bool recognized=false;
-
- for (int i=0;i<saver_count;i++) {
-
- if (!saver[i]->recognize(extension))
- continue;
- recognized=true;
- err = saver[i]->save(p_path,p_scene,p_flags,p_optimizer);
- if (err == OK )
- return OK;
- }
-
- if (err) {
- if (!recognized) {
- ERR_EXPLAIN("No saver format found for scene: "+p_path);
- } else {
- ERR_EXPLAIN("Couldn't save scene: "+p_path);
- }
- ERR_FAIL_V(err);
- }
-
- return err;
-}
-
-void SceneSaver::get_recognized_extensions(List<String> *p_extensions) {
-
- for (int i=0;i<saver_count;i++) {
-
- saver[i]->get_recognized_extensions(p_extensions);
- }
-}
-
-void SceneSaver::add_scene_format_saver(SceneFormatSaver *p_format_saver) {
-
- ERR_FAIL_COND( saver_count >= MAX_SAVERS );
- saver[saver_count++]=p_format_saver;
-}
-
-#endif
diff --git a/scene/io/scene_saver.h b/scene/io/scene_saver.h
deleted file mode 100644
index 3028dce133..0000000000
--- a/scene/io/scene_saver.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*************************************************************************/
-/* scene_saver.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 SCENE_SAVER_H
-#define SCENE_SAVER_H
-
-#include "scene/main/node.h"
-#include "io/object_saver.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-class SceneFormatSaver {
-public:
-
- virtual Error save(const String &p_path,const Node* p_scen,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>())=0;
- virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
- bool recognize(const String& p_extension) const;
- virtual ~SceneFormatSaver() {}
-};
-
-
-
-
-class SceneSaver {
-
- enum {
- MAX_SAVERS=64
- };
-
- static SceneFormatSaver *saver[MAX_SAVERS];
- static int saver_count;
-
-public:
- enum SaverFlags {
-
- FLAG_RELATIVE_PATHS=1,
- FLAG_BUNDLE_RESOURCES=2,
- FLAG_BUNDLE_INSTANCED_SCENES=4,
- FLAG_OMIT_EDITOR_PROPERTIES=8,
- FLAG_SAVE_BIG_ENDIAN=16
- };
-
- static Error save(const String &p_path,const Node* p_scenezz,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>());
- static void add_scene_format_saver(SceneFormatSaver *p_format_saver);
- static void get_recognized_extensions(List<String> *p_extensions);
-};
-
-
-
-#endif
-#endif
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 5d89ee80f1..fbdc87a7cc 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -28,7 +28,6 @@
/*************************************************************************/
#include "node.h"
#include "print_string.h"
-#include "scene/io/scene_loader.h"
#include "message_queue.h"
#include "scene/scene_string_names.h"
#include "scene/resources/packed_scene.h"
@@ -65,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) {
@@ -84,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)
@@ -105,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: {
@@ -151,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 {
@@ -166,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++;
@@ -192,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--;
@@ -202,7 +201,7 @@ void Node::_propagate_enter_scene() {
-void Node::_propagate_exit_scene() {
+void Node::_propagate_exit_tree() {
//block while removing children
@@ -210,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--;
@@ -218,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;
}
@@ -261,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++;
@@ -272,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 );
@@ -311,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)
@@ -334,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
@@ -373,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) {
@@ -386,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;
}
}
@@ -396,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;
}
@@ -420,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;
}
@@ -443,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)
@@ -463,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)
@@ -483,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)
@@ -521,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();
}
}
@@ -631,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 */
@@ -720,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);
@@ -756,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;
@@ -852,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);
@@ -1024,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;
@@ -1053,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;
@@ -1071,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);
@@ -1132,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++;
@@ -1235,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);
@@ -1425,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);
@@ -1611,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;
}
@@ -1651,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;
@@ -1683,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 {
@@ -1712,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() {
@@ -1729,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);
@@ -1766,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));
@@ -1781,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 );
@@ -1799,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") );
@@ -1810,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")) );
@@ -1828,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 bcdc50c880..ed3e419359 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,7 +846,7 @@ 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);
@@ -850,13 +854,13 @@ void SceneMainLoop::queue_delete(Object *p_object) {
}
-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 +963,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;
@@ -968,35 +972,51 @@ void SceneMainLoop::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect
}
-void SceneMainLoop::_bind_methods() {
+#ifdef TOOLS_ENABLED
+void SceneTree::set_edited_scene_root(Node *p_node) {
+ edited_scene_root=p_node;
+}
+
+Node *SceneTree::get_edited_scene_root() const {
+
+ return edited_scene_root;
+}
+#endif
+
+
+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"),&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;
@@ -1010,7 +1030,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") ) );
@@ -1031,14 +1051,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";
@@ -1069,13 +1089,17 @@ SceneMainLoop::SceneMainLoop() {
root->set_physics_object_picking(GLOBAL_DEF("physics/enable_object_picking",true));
+#ifdef TOOLS_ENABLED
+ edited_scene_root=NULL;
+#endif
+
ADD_SIGNAL( MethodInfo("idle_frame"));
ADD_SIGNAL( MethodInfo("fixed_frame"));
}
-SceneMainLoop::~SceneMainLoop() {
+SceneTree::~SceneTree() {
}
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index 493644d2bc..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:
@@ -102,6 +102,9 @@ private:
int64_t current_frame;
int node_count;
+#ifdef TOOLS_ENABLED
+ Node *edited_scene_root;
+#endif
struct UGCall {
StringName group;
@@ -223,15 +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 25d1c8530e..f718a09577 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -36,8 +36,13 @@ void Timer::_notification(int p_what) {
case NOTIFICATION_READY: {
- if (autostart)
+ if (autostart) {
+#ifdef TOOLS_ENABLED
+ 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();
+ }
} break;
case NOTIFICATION_PROCESS: {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 92dcef803c..e6c787cf9e 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -95,8 +95,8 @@ 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);
@@ -113,7 +113,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 +135,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);
@@ -164,13 +166,16 @@ void Viewport::_parent_visibility_changed() {
Control *c = parent->cast_to<Control>();
VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,c->is_visible());
+
+ _update_listener();
+ _update_listener_2d();
}
}
-void Viewport::_vp_enter_scene() {
+void Viewport::_vp_enter_tree() {
Node *parent = get_parent();
//none?
@@ -195,7 +200,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>()) {
@@ -226,19 +231,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) {
@@ -266,7 +271,7 @@ void Viewport::_test_new_mouseover(ObjectID new_collider) {
physics_object_over=new_collider;
}
-
+#endif
}
@@ -275,11 +280,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();
@@ -329,7 +334,7 @@ void Viewport::_notification(int p_what) {
}
#endif
} break;
- case NOTIFICATION_EXIT_SCENE: {
+ case NOTIFICATION_EXIT_TREE: {
@@ -337,7 +342,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());
@@ -348,7 +353,7 @@ void Viewport::_notification(int p_what) {
case NOTIFICATION_FIXED_PROCESS: {
if (physics_object_picking) {
-
+#ifndef _3D_DISABLED
Vector2 last_pos(1e20,1e20);
CollisionObject *last_object;
ObjectID last_id=0;
@@ -394,7 +399,7 @@ void Viewport::_notification(int p_what) {
if (obj) {
CollisionObject *co = obj->cast_to<CollisionObject>();
if (co) {
- co->_input_event(ev,Vector3(),Vector3(),0);
+ co->_input_event(camera,ev,Vector3(),Vector3(),0);
captured=true;
if (ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && !ev.mouse_button.pressed) {
physics_object_capture=0;
@@ -416,7 +421,7 @@ void Viewport::_notification(int p_what) {
if (last_id) {
if (ObjectDB::get_instance(last_id)) {
//good, exists
- last_object->_input_event(ev,result.position,result.normal,result.shape);
+ last_object->_input_event(camera,ev,result.position,result.normal,result.shape);
if (last_object->get_capture_input_on_drag() && ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && ev.mouse_button.pressed) {
physics_object_capture=last_id;
}
@@ -440,10 +445,13 @@ void Viewport::_notification(int p_what) {
bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
ObjectID new_collider=0;
if (col) {
+
if (result.collider) {
+
CollisionObject *co = result.collider->cast_to<CollisionObject>();
if (co) {
- co->_input_event(ev,result.position,result.normal,result.shape);
+
+ co->_input_event(camera,ev,result.position,result.normal,result.shape);
last_object=co;
last_id=result.collider_id;
new_collider=last_id;
@@ -491,6 +499,7 @@ void Viewport::_notification(int p_what) {
}
}
+#endif
}
} break;
@@ -507,6 +516,7 @@ void Viewport::set_rect(const Rect2& p_rect) {
if (rect==p_rect)
return;
rect=p_rect;
+
_update_rect();
_update_stretch_transform();
@@ -541,7 +551,7 @@ Rect2 Viewport::get_rect() const {
void Viewport::_update_listener() {
- if (is_inside_scene() && audio_listener && camera) {
+ 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());
@@ -552,7 +562,7 @@ void Viewport::_update_listener() {
void Viewport::_update_listener_2d() {
- if (is_inside_scene() && audio_listener_2d)
+ 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());
@@ -731,7 +741,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>();
@@ -760,7 +770,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>();
@@ -791,7 +801,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
@@ -801,7 +811,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
@@ -811,7 +821,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());
}
@@ -899,12 +909,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) {
@@ -1023,13 +1033,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: {
@@ -1044,8 +1057,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;
@@ -1089,24 +1102,24 @@ void Viewport::_vp_unhandled_input(const InputEvent& p_ev) {
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);
@@ -1121,7 +1134,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
@@ -1134,7 +1147,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
@@ -1144,7 +1157,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());
}
@@ -1179,6 +1192,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() {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 5d68438f0d..4bb5735731 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -110,6 +110,7 @@ friend class RenderTargetTexture;
Size2 size_override_size;
Size2 size_override_margin;
+ Rect2 last_vp_rect;
bool transparent_bg;
bool render_target_vflip;
@@ -158,8 +159,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);
@@ -229,6 +230,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;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 2a1cca6a3a..8f28a3116e 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -32,14 +32,13 @@
#include "scene/io/resource_format_image.h"
#include "scene/io/resource_format_wav.h"
-#include "scene/io/scene_format_script.h"
+//#include "scene/io/scene_format_script.h"
#include "resources/default_theme/default_theme.h"
#include "object_type_db.h"
#include "scene/main/canvas_layer.h"
#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"
@@ -75,6 +74,8 @@
#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/resources/video_stream.h"
#include "scene/2d/particles_2d.h"
#include "scene/2d/path_2d.h"
@@ -100,6 +101,7 @@
#include "scene/2d/sample_player_2d.h"
#include "scene/2d/screen_button.h"
#include "scene/2d/remote_transform_2d.h"
+#include "scene/2d/y_sort.h"
#include "scene/2d/position_2d.h"
#include "scene/2d/tile_map.h"
@@ -119,7 +121,7 @@
#include "scene/resources/scene_preloader.h"
#include "scene/main/timer.h"
-#include "scene/io/scene_format_object.h"
+
#include "scene/audio/stream_player.h"
#include "scene/audio/event_player.h"
#include "scene/audio/sound_room_params.h"
@@ -141,7 +143,7 @@
#include "scene/resources/mesh_library.h"
-#include "scene/resources/image_path_finder.h"
+
#include "scene/resources/polygon_path_finder.h"
#include "scene/resources/sample.h"
@@ -151,6 +153,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"
@@ -173,9 +177,8 @@
#ifndef _3D_DISABLED
#include "scene/3d/camera.h"
-#include "scene/3d/editable_shape.h"
+
#include "scene/3d/interpolated_camera.h"
-#include "scene/3d/follow_camera.h"
#include "scene/3d/position_3d.h"
#include "scene/3d/test_cube.h"
#include "scene/3d/mesh_instance.h"
@@ -185,7 +188,7 @@
#include "scene/3d/portal.h"
#include "scene/resources/environment.h"
#include "scene/3d/physics_body.h"
-#include "scene/3d/car_body.h"
+
#include "scene/3d/vehicle_body.h"
#include "scene/3d/body_shape.h"
#include "scene/3d/area.h"
@@ -203,7 +206,7 @@
#include "scene/3d/collision_polygon.h"
#endif
-#include "scene/scene_binds.h"
+
static ResourceFormatLoaderImage *resource_loader_image=NULL;
static ResourceFormatLoaderWAV *resource_loader_wav=NULL;
@@ -215,15 +218,6 @@ static ResourceFormatLoaderBitMap *resource_loader_bitmap=NULL;
#endif
static ResourceFormatLoaderTheme *resource_loader_theme=NULL;
static ResourceFormatLoaderShader *resource_loader_shader=NULL;
-#ifdef OLD_SCENE_FORMAT_ENABLED
-static SceneFormatSaverObject *scene_saver_object=NULL;
-static SceneFormatLoaderObject *scene_loader_object=NULL;
-//static SceneFormatLoaderScript *scene_loader_script=NULL;
-#endif
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-SceneIO *scene_io=NULL;
-#endif
//static SceneStringNames *string_names;
@@ -235,13 +229,6 @@ void register_scene_types() {
Node::init_node_hrcr();
-#ifdef OLD_SCENE_FORMAT_ENABLED
- ObjectTypeDB::register_type<SceneIO>();
- ObjectTypeDB::register_virtual_type<SceneInteractiveLoader>();
- scene_io = memnew( SceneIO );
- Globals::get_singleton()->add_singleton(Globals::Singleton("SceneIO",scene_io));
-#endif
-
resource_loader_image = memnew( ResourceFormatLoaderImage );
ResourceLoader::add_resource_format_loader( resource_loader_image );
@@ -262,16 +249,6 @@ void register_scene_types() {
resource_loader_shader = memnew( ResourceFormatLoaderShader );
ResourceLoader::add_resource_format_loader( resource_loader_shader );
-#ifdef OLD_SCENE_FORMAT_ENABLED
- scene_saver_object=memnew( SceneFormatSaverObject );
- SceneSaver::add_scene_format_saver(scene_saver_object);
-
- scene_loader_object=memnew( SceneFormatLoaderObject );
- SceneLoader::add_scene_format_loader(scene_loader_object);
-
-// scene_loader_script=memnew( SceneFormatLoaderScript );
-// SceneLoader::add_scene_format_loader(scene_loader_script);
-#endif
make_default_theme();
@@ -294,7 +271,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>();
@@ -329,6 +307,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
@@ -378,7 +358,6 @@ void register_scene_types() {
ObjectTypeDB::register_type<BoneAttachment>();
ObjectTypeDB::register_virtual_type<VisualInstance>();
ObjectTypeDB::register_type<Camera>();
- ObjectTypeDB::register_type<FollowCamera>();
ObjectTypeDB::register_type<InterpolatedCamera>();
ObjectTypeDB::register_type<TestCube>();
ObjectTypeDB::register_type<MeshInstance>();
@@ -404,8 +383,8 @@ void register_scene_types() {
ObjectTypeDB::register_type<StaticBody>();
ObjectTypeDB::register_type<RigidBody>();
ObjectTypeDB::register_type<KinematicBody>();
- ObjectTypeDB::register_type<CarBody>();
- ObjectTypeDB::register_type<CarWheel>();
+
+
ObjectTypeDB::register_type<VehicleBody>();
ObjectTypeDB::register_type<VehicleWheel>();
ObjectTypeDB::register_type<Area>();
@@ -413,8 +392,6 @@ void register_scene_types() {
ObjectTypeDB::register_type<CollisionShape>();
ObjectTypeDB::register_type<CollisionPolygon>();
ObjectTypeDB::register_type<RayCast>();
- ObjectTypeDB::register_virtual_type<EditableShape>();
- ObjectTypeDB::register_type<EditableSphere>();
ObjectTypeDB::register_type<MultiMeshInstance>();
ObjectTypeDB::register_type<Room>();
ObjectTypeDB::register_type<Curve3D>();
@@ -423,8 +400,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
@@ -433,6 +418,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())) );
@@ -450,12 +436,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>();
@@ -491,6 +471,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<VisibilityNotifier2D>();
ObjectTypeDB::register_type<VisibilityEnabler2D>();
ObjectTypeDB::register_type<Polygon2D>();
+ ObjectTypeDB::register_type<YSort>();
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false);
@@ -519,11 +500,16 @@ void register_scene_types() {
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_virtual_type<Shader>();
+ ObjectTypeDB::register_virtual_type<ShaderGraph>();
+ ObjectTypeDB::register_type<MaterialShaderGraph>();
+ ObjectTypeDB::register_type<MaterialShader>();
+ ObjectTypeDB::register_type<CanvasItemShader>();
+ 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,7 +545,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<StyleBoxFlat>();
ObjectTypeDB::register_type<StyleBoxImageMask>();
ObjectTypeDB::register_type<Theme>();
- ObjectTypeDB::register_type<ImagePathFinder>();
+
ObjectTypeDB::register_type<PolygonPathFinder>();
ObjectTypeDB::register_type<BitMap>();
@@ -590,12 +576,8 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
ObjectTypeDB::register_type<PackedScene>();
-#ifdef OLD_SCENE_FORMAT_ENABLED
- ObjectTypeDB::register_type<ScenePreloader>();
-#endif
-
- ObjectTypeDB::register_type<SceneMainLoop>();
+ ObjectTypeDB::register_type<SceneTree>();
OS::get_singleton()->yield(); //may take time to init
@@ -617,11 +599,5 @@ void unregister_scene_types() {
memdelete( resource_loader_theme );
memdelete( resource_loader_shader );
-#ifdef OLD_SCENE_FORMAT_ENABLED
- memdelete( scene_saver_object );
- memdelete( scene_loader_object );
-// memdelete( scene_loader_script );
- memdelete( scene_io );
-#endif
SceneStringNames::free();
}
diff --git a/scene/resources/SCsub b/scene/resources/SCsub
index 87bd33e00e..eaa282ae1a 100644
--- a/scene/resources/SCsub
+++ b/scene/resources/SCsub
@@ -1,6 +1,7 @@
Import('env')
env.add_source_files(env.scene_sources,"*.cpp")
+env.add_source_files(env.scene_sources,"*.c")
Export('env')
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 67f45ced2b..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,185 +1716,222 @@ void Animation::clear() {
}
-void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err) {
- 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;
- Quat r02 = (q0.inverse() * q2).normalized();
- Quat r01 = (q0.inverse() * q1).normalized();
+ } else {
- Vector3 v02,v01;
- real_t a02,a01;
- r02.get_axis_and_angle(v02,a02);
- r01.get_axis_and_angle(v01,a01);
+ Quat r02 = (q0.inverse() * q2).normalized();
+ Quat r01 = (q0.inverse() * q1).normalized();
- if (v01.dot(v02)<0) {
- //make sure both rotations go the same way to compare
- v02=-v02;
- a02=-a02;
- }
+ Vector3 v02,v01;
+ real_t a02,a01;
- 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;
- }
+ r02.get_axis_and_angle(v02,a02);
+ r01.get_axis_and_angle(v01,a01);
- if (a01*a02 < 0 ) {
- //not rotating in the same direction
- continue;
- }
+ if (Math::abs(a02)>p_max_optimizable_angle)
+ return false;
- real_t tr = a01/a02;
- if (tr<0 || tr>1)
- continue; //rotating too much or too less
+ if (v01.dot(v02)<0) {
+ //make sure both rotations go the same way to compare
+ v02=-v02;
+ a02=-a02;
+ }
- t[1]=tr;
+ 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;
+ }
+ if (a01*a02 < 0 ) {
+ //not rotating in the same direction
+ return false;
}
+ 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;
}
@@ -1905,7 +1942,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
}
-void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err) {
+void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err,float p_angle_max) {
int total_tt=0;
@@ -1913,7 +1950,7 @@ void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err)
for(int i=0;i<tracks.size();i++) {
if (tracks[i]->type==TYPE_TRANSFORM)
- _transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err);
+ _transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err,p_angle_max);
}
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 4c4e2f0275..bf87789e39 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -204,7 +204,8 @@ private:
return idxr;
}
- void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01);
+ 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:
@@ -271,7 +272,7 @@ public:
void clear();
- void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01);
+ void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125);
Animation();
~Animation();
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..6c27ffc6d9 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();
@@ -956,7 +956,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();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index d10bb37f60..e7f0d9b1f5 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;
}
@@ -331,6 +331,7 @@ void make_default_theme() {
t->set_color("current_line_color","TextEdit", Color(0.3,0.5,0.8,0.15) );
t->set_color("cursor_color","TextEdit", control_font_color );
t->set_color("symbol_color","TextEdit", control_font_color_hover );
+ t->set_color("brace_mismatch_color","TextEdit", Color(1,0.2,0.2) );
t->set_constant("line_spacing","TextEdit",1 );
t->set_stylebox("scroll","HScrollBar", make_stylebox( hscroll_bg_png,3,3,3,3,0,0,0,0) );
@@ -415,7 +416,21 @@ void make_default_theme() {
t->set_color("font_color_hover","PopupMenu", control_font_color );
t->set_constant("hseparation","PopupMenu",2);
t->set_constant("vseparation","PopupMenu",1);
-
+
+ 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);
+
+
t->set_stylebox("bg","Tree", make_stylebox( tree_bg_png,4,4,4,5,3,3,3,3) );
t->set_stylebox("bg_focus","Tree", focus );
Ref<StyleBoxTexture> tree_selected = make_stylebox( selection_png,4,4,4,4);
diff --git a/scene/resources/default_theme/graph_node.png b/scene/resources/default_theme/graph_node.png
new file mode 100644
index 0000000000..3adccf2c3b
--- /dev/null
+++ b/scene/resources/default_theme/graph_node.png
Binary files differ
diff --git a/scene/resources/default_theme/graph_node_close.png b/scene/resources/default_theme/graph_node_close.png
new file mode 100644
index 0000000000..ea5b510418
--- /dev/null
+++ b/scene/resources/default_theme/graph_node_close.png
Binary files differ
diff --git a/scene/resources/default_theme/graph_port.png b/scene/resources/default_theme/graph_port.png
new file mode 100644
index 0000000000..92f425f977
--- /dev/null
+++ b/scene/resources/default_theme/graph_port.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 9cef0265ee..a0f3dcd988 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -99,6 +99,21 @@ static const unsigned char full_panel_bg_png[]={
};
+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 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 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
+};
+
+
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
};
diff --git a/scene/resources/image_path_finder.cpp b/scene/resources/image_path_finder.cpp
deleted file mode 100644
index 1a7758789c..0000000000
--- a/scene/resources/image_path_finder.cpp
+++ /dev/null
@@ -1,427 +0,0 @@
-/*************************************************************************/
-/* image_path_finder.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 "image_path_finder.h"
-
-
-void ImagePathFinder::_unlock() {
-
- lock=DVector<Cell>::Write();
- cells=NULL;
-
-}
-
-void ImagePathFinder::_lock() {
-
- lock = cell_data.write();
- cells=lock.ptr();
-
-}
-
-
-bool ImagePathFinder::_can_go_straigth(const Point2& p_from, const Point2& p_to) const {
-
- int x1=p_from.x;
- int y1=p_from.y;
- int x2=p_to.x;
- int y2=p_to.y;
-
-#define _TEST_VALID \
- {\
- uint32_t ofs=drawy*width+drawx;\
- if (cells[ofs].solid) {\
- if (!((drawx>0 && cells[ofs-1].visited) ||\
- (drawx<width-1 && cells[ofs+1].visited) ||\
- (drawy>0 && cells[ofs-width].visited) ||\
- (drawy<height-1 && cells[ofs+width].visited))) {\
- return false;\
- }\
- }\
- }\
-
-
- int n, deltax, deltay, sgndeltax, sgndeltay, deltaxabs, deltayabs, x, y, drawx, drawy;
- deltax = x2 - x1;
- deltay = y2 - y1;
- deltaxabs = ABS(deltax);
- deltayabs = ABS(deltay);
- sgndeltax = SGN(deltax);
- sgndeltay = SGN(deltay);
- x = deltayabs >> 1;
- y = deltaxabs >> 1;
- drawx = x1;
- drawy = y1;
- int pc=0;
-
- _TEST_VALID
-
- if(deltaxabs >= deltayabs) {
- for(n = 0; n < deltaxabs; n++) {
- y += deltayabs;
- if(y >= deltaxabs){
- y -= deltaxabs;
- drawy += sgndeltay;
- }
- drawx += sgndeltax;
- _TEST_VALID
- }
- } else {
- for(n = 0; n < deltayabs; n++) {
- x += deltaxabs;
- if(x >= deltayabs) {
- x -= deltayabs;
- drawx += sgndeltax;
- }
- drawy += sgndeltay;
- _TEST_VALID
- }
- }
- return true;
-
-
-}
-
-bool ImagePathFinder::_is_linear_path(const Point2& p_from, const Point2& p_to) {
-
- int x1=p_from.x;
- int y1=p_from.y;
- int x2=p_to.x;
- int y2=p_to.y;
-
-#define _TEST_CELL \
- if (cells[drawy*width+drawx].solid)\
- return false;
-
-
- int n, deltax, deltay, sgndeltax, sgndeltay, deltaxabs, deltayabs, x, y, drawx, drawy;
- deltax = x2 - x1;
- deltay = y2 - y1;
- deltaxabs = ABS(deltax);
- deltayabs = ABS(deltay);
- sgndeltax = SGN(deltax);
- sgndeltay = SGN(deltay);
- x = deltayabs >> 1;
- y = deltaxabs >> 1;
- drawx = x1;
- drawy = y1;
- int pc=0;
-
- _TEST_CELL
-
- if(deltaxabs >= deltayabs) {
- for(n = 0; n < deltaxabs; n++) {
- y += deltayabs;
- if(y >= deltaxabs){
- y -= deltaxabs;
- drawy += sgndeltay;
- }
- drawx += sgndeltax;
- _TEST_CELL
- }
- } else {
- for(n = 0; n < deltayabs; n++) {
- x += deltaxabs;
- if(x >= deltayabs) {
- x -= deltayabs;
- drawx += sgndeltax;
- }
- drawy += sgndeltay;
- _TEST_CELL
- }
- }
- return true;
-}
-
-
-DVector<Point2> ImagePathFinder::find_path(const Point2& p_from, const Point2& p_to,bool p_optimize) {
-
-
- Point2i from=p_from;
- Point2i to=p_to;
-
- ERR_FAIL_COND_V(from.x < 0,DVector<Point2>());
- ERR_FAIL_COND_V(from.y < 0,DVector<Point2>());
- ERR_FAIL_COND_V(from.x >=width,DVector<Point2>());
- ERR_FAIL_COND_V(from.y >=height,DVector<Point2>());
- ERR_FAIL_COND_V(to.x < 0,DVector<Point2>());
- ERR_FAIL_COND_V(to.y < 0,DVector<Point2>());
- ERR_FAIL_COND_V(to.x >=width,DVector<Point2>());
- ERR_FAIL_COND_V(to.y >=height,DVector<Point2>());
-
- if (from==to) {
- DVector<Point2> p;
- p.push_back(from);
- return p;
- }
-
- _lock();
-
-
- if (p_optimize) { //try a line first
-
- if (_is_linear_path(p_from,p_to)) {
- _unlock();
- DVector<Point2> p;
- p.push_back(from);
- p.push_back(to);
- return p;
- }
- }
-
-
- //clear all
- for(int i=0;i<width*height;i++) {
-
- bool s = cells[i].solid;
- cells[i].data=0;
- cells[i].solid=s;
- }
-
-#define CELL_INDEX(m_p) (m_p.y*width+m_p.x)
-#define CELL_COST(m_p) (cells[CELL_INDEX(m_p)].cost+( ABS(m_p.x-to.x)+ABS(m_p.y-to.y))*10)
-
-
- Set<Point2i> pending;
- pending.insert(from);
-
- //helper constants
- static const Point2i neighbour_rel[8]={
- Point2i(-1,-1), //0
- Point2i(-1, 0), //1
- Point2i(-1,+1), //2
- Point2i( 0,-1), //3
- Point2i( 0,+1), //4
- Point2i(+1,-1), //5
- Point2i(+1, 0), //6
- Point2i(+1,+1) }; //7
-
- static const int neighbour_cost[8]={
- 14,
- 10,
- 14,
- 10,
- 10,
- 14,
- 10,
- 14
- };
-
- static const int neighbour_parent[8]={
- 7,
- 6,
- 5,
- 4,
- 3,
- 2,
- 1,
- 0,
- };
-
- while(true) {
-
- if (pending.size() == 0) {
- _unlock();
- return DVector<Point2>(); // points don't connect
- }
- Point2i current;
- int lc=0x7FFFFFFF;
- { //find the one with the least cost
-
- Set<Point2i>::Element *Efound=NULL;
- for (Set<Point2i>::Element *E=pending.front();E;E=E->next()) {
-
- int cc =CELL_COST(E->get());
- if (cc<lc) {
- lc=cc;
- current=E->get();
- Efound=E;
-
- }
-
- }
- pending.erase(Efound);
- }
-
- Cell &c = cells[CELL_INDEX(current)];
-
- //search around other cells
-
-
- int accum_cost = (from==current) ? 0 : cells[CELL_INDEX((current + neighbour_rel[c.parent]))].cost;
-
- bool done=false;
-
- for(int i=0;i<8;i++) {
-
- Point2i neighbour=current+neighbour_rel[i];
- if (neighbour.x<0 || neighbour.y<0 || neighbour.x>=width || neighbour.y>=height)
- continue;
-
- Cell &n = cells[CELL_INDEX(neighbour)];
- if (n.solid)
- continue; //no good
-
- int cost = neighbour_cost[i]+accum_cost;
-
- if (n.visited && n.cost < cost)
- continue;
-
- n.cost=cost;
- n.parent=neighbour_parent[i];
- n.visited=true;
- pending.insert(neighbour);
- if (neighbour==to)
- done=true;
-
- }
-
- if (done)
- break;
- }
-
-
- // go througuh poins twice, first compute amount, then add them
-
- Point2i current=to;
- int pcount=0;
-
- while(true) {
-
- Cell &c = cells[CELL_INDEX(current)];
- c.visited=true;
- pcount++;
- if (current==from)
- break;
- current+=neighbour_rel[ c.parent ];
- }
-
- //now place them in an array
- DVector<Vector2> result;
- result.resize(pcount);
-
- DVector<Vector2>::Write res=result.write();
-
- current=to;
- int pidx=pcount-1;
-
- while(true) {
-
- Cell &c = cells[CELL_INDEX(current)];
- res[pidx]=current;
- pidx--;
- if (current==from)
- break;
- current+=neighbour_rel[ c.parent ];
- }
-
-
- //simplify..
-
-
- if (p_optimize) {
-
- int p=pcount-1;
- while(p>0) {
-
-
- int limit=p;
- while(limit>0) {
-
- limit--;
- if (!_can_go_straigth(res[p],res[limit]))
- break;
- }
-
-
- if (limit<p-1) {
- int diff = p-limit-1;
- pcount-=diff;
- for(int i=limit+1;i<pcount;i++) {
-
- res[i]=res[i+diff];
- }
- }
- p=limit;
- }
- }
-
- res=DVector<Vector2>::Write();
- result.resize(pcount);
- return result;
-}
-
-Size2 ImagePathFinder::get_size() const {
-
- return Size2(width,height);
-}
-bool ImagePathFinder::is_solid(const Point2& p_pos) {
-
-
- Point2i pos = p_pos;
-
- ERR_FAIL_COND_V(pos.x<0,true);
- ERR_FAIL_COND_V(pos.y<0,true);
- ERR_FAIL_COND_V(pos.x>=width,true);
- ERR_FAIL_COND_V(pos.y>=height,true);
-
- return cell_data[pos.y*width+pos.x].solid;
-}
-
-void ImagePathFinder::create_from_image_alpha(const Image& p_image) {
-
- ERR_FAIL_COND(p_image.get_format() != Image::FORMAT_RGBA);
- width = p_image.get_width();
- height = p_image.get_height();
- DVector<uint8_t> data = p_image.get_data();
- cell_data.resize(width * height);
- DVector<uint8_t>::Read read = data.read();
- DVector<Cell>::Write write = cell_data.write();
- for (int i=0; i<width * height; i++) {
- Cell cell;
- cell.data = 0;
- cell.solid = read[i*4+3] < 128;
- write[i] = cell;
- };
-};
-
-
-void ImagePathFinder::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("find_path","from","to","optimize"),&ImagePathFinder::find_path,DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("get_size"),&ImagePathFinder::get_size);
- ObjectTypeDB::bind_method(_MD("is_solid","pos"),&ImagePathFinder::is_solid);
- ObjectTypeDB::bind_method(_MD("create_from_image_alpha"),&ImagePathFinder::create_from_image_alpha);
-}
-
-ImagePathFinder::ImagePathFinder()
-{
-
- cells=NULL;
- width=0;
- height=0;
-}
diff --git a/scene/resources/image_path_finder.h b/scene/resources/image_path_finder.h
deleted file mode 100644
index e975ea5ed9..0000000000
--- a/scene/resources/image_path_finder.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************************************/
-/* image_path_finder.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 IMAGE_PATH_FINDER_H
-#define IMAGE_PATH_FINDER_H
-
-#include "resource.h"
-
-class ImagePathFinder : public Resource{
-
-
- OBJ_TYPE(ImagePathFinder,Resource);
- union Cell {
-
- struct {
- bool solid:1;
- bool visited:1;
- bool final:1;
- uint8_t parent:3;
- uint32_t cost:26;
- };
-
- uint32_t data;
- };
-
-
-
-
-
- DVector<Cell>::Write lock;
- DVector<Cell> cell_data;
-
- uint32_t width;
- uint32_t height;
- Cell* cells; //when unlocked
-
- void _unlock();
- void _lock();
-
-
- _FORCE_INLINE_ bool _can_go_straigth(const Point2& p_from, const Point2& p_to) const;
- _FORCE_INLINE_ bool _is_linear_path(const Point2& p_from, const Point2& p_to);
-
-protected:
-
- static void _bind_methods();
-public:
-
- DVector<Point2> find_path(const Point2& p_from, const Point2& p_to,bool p_optimize=false);
- Size2 get_size() const;
- bool is_solid(const Point2& p_pos);
- void create_from_image_alpha(const Image& p_image);
-
-
-
- ImagePathFinder();
-};
-
-#endif // IMAGE_PATH_FINDER_H
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 2314926b2b..355cc8884c 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -36,7 +36,8 @@ static const char*_flag_names[Material::FLAG_MAX]={
"invert_faces",
"unshaded",
"on_top",
- "lightmap_on_uv2"
+ "lightmap_on_uv2",
+ "colarray_is_srgb"
};
@@ -46,7 +47,8 @@ static const Material::Flag _flag_indices[Material::FLAG_MAX]={
Material::FLAG_INVERT_FACES,
Material::FLAG_UNSHADED,
Material::FLAG_ONTOP,
- Material::FLAG_LIGHTMAP_ON_UV2
+ Material::FLAG_LIGHTMAP_ON_UV2,
+ Material::FLAG_COLOR_ARRAY_SRGB,
};
@@ -132,6 +134,8 @@ void Material::_bind_methods() {
BIND_CONSTANT( FLAG_INVERT_FACES );
BIND_CONSTANT( FLAG_UNSHADED );
BIND_CONSTANT( FLAG_ONTOP );
+ BIND_CONSTANT( FLAG_LIGHTMAP_ON_UV2 );
+ BIND_CONSTANT( FLAG_COLOR_ARRAY_SRGB );
BIND_CONSTANT( FLAG_MAX );
BIND_CONSTANT( DEPTH_DRAW_ALWAYS );
@@ -156,6 +160,8 @@ Material::Material(const RID& p_material) {
flags[FLAG_INVERT_FACES]=false;
flags[FLAG_UNSHADED]=false;
flags[FLAG_ONTOP]=false;
+ flags[FLAG_LIGHTMAP_ON_UV2]=true;
+ flags[FLAG_COLOR_ARRAY_SRGB]=false;
depth_draw_mode=DEPTH_DRAW_OPAQUE_ONLY;
@@ -316,14 +322,14 @@ Transform FixedMaterial::get_uv_transform() const {
void FixedMaterial::set_fixed_flag(FixedFlag p_flag, bool p_value) {
- ERR_FAIL_INDEX(p_flag,4);
+ ERR_FAIL_INDEX(p_flag,5);
fixed_flags[p_flag]=p_value;
VisualServer::get_singleton()->fixed_material_set_flag(material,(VS::FixedMaterialFlags)p_flag,p_value);
}
bool FixedMaterial::get_fixed_flag(FixedFlag p_flag) const {
- ERR_FAIL_INDEX_V(p_flag,4,false);
+ ERR_FAIL_INDEX_V(p_flag,5,false);
return fixed_flags[p_flag];
}
@@ -371,6 +377,7 @@ void FixedMaterial::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_color_array" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_COLOR_ARRAY);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_point_size" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_POINT_SIZE);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/discard_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_DISCARD_ALPHA);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_xy_normalmap" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_XY_NORMALMAP);
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/diffuse" ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_DIFFUSE);
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/specular", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPECULAR );
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/emission", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_EMISSION );
@@ -426,11 +433,14 @@ FixedMaterial::FixedMaterial() : Material(VS::get_singleton()->fixed_material_cr
param[PARAM_SHADE_PARAM]=0.5;
param[PARAM_DETAIL]=1.0;
-
+ set_flag(FLAG_COLOR_ARRAY_SRGB,true);
fixed_flags[FLAG_USE_ALPHA]=false;
fixed_flags[FLAG_USE_COLOR_ARRAY]=false;
fixed_flags[FLAG_USE_POINT_SIZE]=false;
+ fixed_flags[FLAG_USE_XY_NORMALMAP]=false;
+ fixed_flags[FLAG_DISCARD_ALPHA]=false;
+
for(int i=0;i<PARAM_MAX;i++) {
@@ -448,6 +458,8 @@ FixedMaterial::~FixedMaterial() {
}
+
+
bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) {
if (p_name==SceneStringNames::get_singleton()->shader_shader) {
@@ -455,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;
+ }
}
}
@@ -474,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;
+ }
}
}
@@ -489,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()) {
@@ -540,124 +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);
-}
-
-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) {
-
- 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);
+ 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);
+ ObjectTypeDB::bind_method(_MD("_shader_changed"), &ShaderMaterial::_shader_changed );
}
-bool UnshadedMaterial::is_using_alpha() const{
-
- return alpha;
-}
-void UnshadedMaterial::set_use_color_array(bool p_use_color_array){
+void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
- 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);
+ 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);
+ }
+ }
+ }
+ Material::get_argument_options(p_function,p_idx,r_options);
}
-bool UnshadedMaterial::is_using_color_array() const{
-
- return color_array;
-}
+ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->material_create()){
-UnshadedMaterial::UnshadedMaterial() :Material(VisualServer::get_singleton()->fixed_material_create()){
- set_flag(FLAG_UNSHADED,true);
- set_use_alpha(true);
}
-UnshadedMaterial::~UnshadedMaterial() {
-
-}
+/////////////////////////////////
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 23ecb18fac..73d1a4e188 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -54,6 +54,7 @@ public:
FLAG_UNSHADED = VS::MATERIAL_FLAG_UNSHADED,
FLAG_ONTOP = VS::MATERIAL_FLAG_ONTOP,
FLAG_LIGHTMAP_ON_UV2 = VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2,
+ FLAG_COLOR_ARRAY_SRGB = VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,
FLAG_MAX = VS::MATERIAL_FLAG_MAX
};
@@ -141,7 +142,9 @@ public:
FLAG_USE_ALPHA=VS::FIXED_MATERIAL_FLAG_USE_ALPHA,
FLAG_USE_COLOR_ARRAY=VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,
FLAG_USE_POINT_SIZE=VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE,
- FLAG_DISCARD_ALPHA=VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA
+ FLAG_DISCARD_ALPHA=VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA,
+ FLAG_USE_XY_NORMALMAP=VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP,
+ FLAG_MAX=VS::FIXED_MATERIAL_FLAG_MAX
};
enum LightShader {
@@ -166,7 +169,7 @@ private:
Ref<Texture> texture_param[PARAM_MAX];
TexCoordMode texture_texcoord[PARAM_MAX];
LightShader light_shader;
- bool fixed_flags[3];
+ bool fixed_flags[FLAG_MAX];
float point_size;
@@ -240,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();
};
@@ -249,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 c6e492fcb3..f4bb3088c3 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -29,6 +29,7 @@
#include "mesh.h"
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
+#include "surface_tool.h"
static const char*_array_name[]={
"vertex_array",
@@ -648,6 +649,30 @@ void Mesh::center_geometry() {
}
+void Mesh::regen_normalmaps() {
+
+
+ Vector< Ref<SurfaceTool> > surfs;
+ for(int i=0;i<get_surface_count();i++) {
+
+ Ref<SurfaceTool> st = memnew( SurfaceTool );
+ st->create_from(Ref<Mesh>(this),i);
+ surfs.push_back(st);
+ }
+
+ while (get_surface_count()) {
+ surface_remove(0);
+ }
+
+ for(int i=0;i<surfs.size();i++) {
+
+ surfs[i]->generate_tangents();
+ surfs[i]->commit(Ref<Mesh>(this));
+ }
+}
+
+
+
Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
if (triangle_mesh.is_valid())
@@ -718,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);
@@ -740,6 +984,8 @@ void Mesh::_bind_methods() {
ObjectTypeDB::bind_method(_MD("surface_get_name","surf_idx"),&Mesh::surface_get_name);
ObjectTypeDB::bind_method(_MD("center_geometry"),&Mesh::center_geometry);
ObjectTypeDB::set_method_flags(get_type_static(),_SCS("center_geometry"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ObjectTypeDB::bind_method(_MD("regen_normalmaps"),&Mesh::regen_normalmaps);
+ ObjectTypeDB::set_method_flags(get_type_static(),_SCS("regen_normalmaps"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
ObjectTypeDB::bind_method(_MD("set_custom_aabb","aabb"),&Mesh::set_custom_aabb);
ObjectTypeDB::bind_method(_MD("get_custom_aabb"),&Mesh::get_custom_aabb);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 5243163a4d..5aacc8be57 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -166,7 +166,10 @@ 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();
DVector<Face3> get_faces() const;
Ref<TriangleMesh> generate_triangle_mesh() const;
diff --git a/scene/resources/mikktspace.c b/scene/resources/mikktspace.c
new file mode 100644
index 0000000000..62aa2da251
--- /dev/null
+++ b/scene/resources/mikktspace.c
@@ -0,0 +1,1890 @@
+/** \file mikktspace/mikktspace.c
+ * \ingroup mikktspace
+ */
+/**
+ * Copyright (C) 2011 by Morten S. Mikkelsen
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <float.h>
+#include <stdlib.h>
+
+#include "mikktspace.h"
+
+#define TFALSE 0
+#define TTRUE 1
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795
+#endif
+
+#define INTERNAL_RND_SORT_SEED 39871946
+
+// internal structure
+typedef struct {
+ float x, y, z;
+} SVec3;
+
+static tbool veq( const SVec3 v1, const SVec3 v2 )
+{
+ return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z);
+}
+
+static SVec3 vadd( const SVec3 v1, const SVec3 v2 )
+{
+ SVec3 vRes;
+
+ vRes.x = v1.x + v2.x;
+ vRes.y = v1.y + v2.y;
+ vRes.z = v1.z + v2.z;
+
+ return vRes;
+}
+
+
+static SVec3 vsub( const SVec3 v1, const SVec3 v2 )
+{
+ SVec3 vRes;
+
+ vRes.x = v1.x - v2.x;
+ vRes.y = v1.y - v2.y;
+ vRes.z = v1.z - v2.z;
+
+ return vRes;
+}
+
+static SVec3 vscale(const float fS, const SVec3 v)
+{
+ SVec3 vRes;
+
+ vRes.x = fS * v.x;
+ vRes.y = fS * v.y;
+ vRes.z = fS * v.z;
+
+ return vRes;
+}
+
+static float LengthSquared( const SVec3 v )
+{
+ return v.x*v.x + v.y*v.y + v.z*v.z;
+}
+
+static float Length( const SVec3 v )
+{
+ return sqrtf(LengthSquared(v));
+}
+
+static SVec3 Normalize( const SVec3 v )
+{
+ return vscale(1 / Length(v), v);
+}
+
+static float vdot( const SVec3 v1, const SVec3 v2)
+{
+ return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
+}
+
+
+static tbool NotZero(const float fX)
+{
+ // could possibly use FLT_EPSILON instead
+ return fabsf(fX) > FLT_MIN;
+}
+
+static tbool VNotZero(const SVec3 v)
+{
+ // might change this to an epsilon based test
+ return NotZero(v.x) || NotZero(v.y) || NotZero(v.z);
+}
+
+
+
+typedef struct {
+ int iNrFaces;
+ int * pTriMembers;
+} SSubGroup;
+
+typedef struct {
+ int iNrFaces;
+ int * pFaceIndices;
+ int iVertexRepresentitive;
+ tbool bOrientPreservering;
+} SGroup;
+
+//
+#define MARK_DEGENERATE 1
+#define QUAD_ONE_DEGEN_TRI 2
+#define GROUP_WITH_ANY 4
+#define ORIENT_PRESERVING 8
+
+
+
+typedef struct {
+ int FaceNeighbors[3];
+ SGroup * AssignedGroup[3];
+
+ // normalized first order face derivatives
+ SVec3 vOs, vOt;
+ float fMagS, fMagT; // original magnitudes
+
+ // determines if the current and the next triangle are a quad.
+ int iOrgFaceNumber;
+ int iFlag, iTSpacesOffs;
+ unsigned char vert_num[4];
+} STriInfo;
+
+typedef struct {
+ SVec3 vOs;
+ float fMagS;
+ SVec3 vOt;
+ float fMagT;
+ int iCounter; // this is to average back into quads.
+ tbool bOrient;
+} STSpace;
+
+static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
+static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
+static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
+static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn);
+static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[],
+ const int iNrActiveGroups, const int piTriListIn[], const float fThresCos,
+ const SMikkTSpaceContext * pContext);
+
+static int MakeIndex(const int iFace, const int iVert)
+{
+ assert(iVert>=0 && iVert<4 && iFace>=0);
+ return (iFace<<2) | (iVert&0x3);
+}
+
+static void IndexToData(int * piFace, int * piVert, const int iIndexIn)
+{
+ piVert[0] = iIndexIn&0x3;
+ piFace[0] = iIndexIn>>2;
+}
+
+static STSpace AvgTSpace(const STSpace * pTS0, const STSpace * pTS1)
+{
+ STSpace ts_res;
+
+ // this if is important. Due to floating point precision
+ // averaging when ts0==ts1 will cause a slight difference
+ // which results in tangent space splits later on
+ if (pTS0->fMagS==pTS1->fMagS && pTS0->fMagT==pTS1->fMagT &&
+ veq(pTS0->vOs,pTS1->vOs) && veq(pTS0->vOt, pTS1->vOt))
+ {
+ ts_res.fMagS = pTS0->fMagS;
+ ts_res.fMagT = pTS0->fMagT;
+ ts_res.vOs = pTS0->vOs;
+ ts_res.vOt = pTS0->vOt;
+ }
+ else
+ {
+ ts_res.fMagS = 0.5f*(pTS0->fMagS+pTS1->fMagS);
+ ts_res.fMagT = 0.5f*(pTS0->fMagT+pTS1->fMagT);
+ ts_res.vOs = vadd(pTS0->vOs,pTS1->vOs);
+ ts_res.vOt = vadd(pTS0->vOt,pTS1->vOt);
+ if ( VNotZero(ts_res.vOs) ) ts_res.vOs = Normalize(ts_res.vOs);
+ if ( VNotZero(ts_res.vOt) ) ts_res.vOt = Normalize(ts_res.vOt);
+ }
+
+ return ts_res;
+}
+
+
+
+static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index);
+static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index);
+static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index);
+
+
+// degen triangles
+static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris);
+static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris);
+
+
+tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext)
+{
+ return genTangSpace(pContext, 180.0f);
+}
+
+tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThreshold)
+{
+ // count nr_triangles
+ int * piTriListIn = NULL, * piGroupTrianglesBuffer = NULL;
+ STriInfo * pTriInfos = NULL;
+ SGroup * pGroups = NULL;
+ STSpace * psTspace = NULL;
+ int iNrTrianglesIn = 0, f=0, t=0, i=0;
+ int iNrTSPaces = 0, iTotTris = 0, iDegenTriangles = 0, iNrMaxGroups = 0;
+ int iNrActiveGroups = 0, index = 0;
+ const int iNrFaces = pContext->m_pInterface->m_getNumFaces(pContext);
+ tbool bRes = TFALSE;
+ const float fThresCos = (float) cos((fAngularThreshold*(float)M_PI)/180.0f);
+
+ // verify all call-backs have been set
+ if ( pContext->m_pInterface->m_getNumFaces==NULL ||
+ pContext->m_pInterface->m_getNumVerticesOfFace==NULL ||
+ pContext->m_pInterface->m_getPosition==NULL ||
+ pContext->m_pInterface->m_getNormal==NULL ||
+ pContext->m_pInterface->m_getTexCoord==NULL )
+ return TFALSE;
+
+ // count triangles on supported faces
+ for (f=0; f<iNrFaces; f++)
+ {
+ const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f);
+ if (verts==3) ++iNrTrianglesIn;
+ else if (verts==4) iNrTrianglesIn += 2;
+ }
+ if (iNrTrianglesIn<=0) return TFALSE;
+
+ // allocate memory for an index list
+ piTriListIn = (int *) malloc(sizeof(int)*3*iNrTrianglesIn);
+ pTriInfos = (STriInfo *) malloc(sizeof(STriInfo)*iNrTrianglesIn);
+ if (piTriListIn==NULL || pTriInfos==NULL)
+ {
+ if (piTriListIn!=NULL) free(piTriListIn);
+ if (pTriInfos!=NULL) free(pTriInfos);
+ return TFALSE;
+ }
+
+ // make an initial triangle --> face index list
+ iNrTSPaces = GenerateInitialVerticesIndexList(pTriInfos, piTriListIn, pContext, iNrTrianglesIn);
+
+ // make a welded index list of identical positions and attributes (pos, norm, texc)
+ //printf("gen welded index list begin\n");
+ GenerateSharedVerticesIndexList(piTriListIn, pContext, iNrTrianglesIn);
+ //printf("gen welded index list end\n");
+
+ // Mark all degenerate triangles
+ iTotTris = iNrTrianglesIn;
+ iDegenTriangles = 0;
+ for (t=0; t<iTotTris; t++)
+ {
+ const int i0 = piTriListIn[t*3+0];
+ const int i1 = piTriListIn[t*3+1];
+ const int i2 = piTriListIn[t*3+2];
+ const SVec3 p0 = GetPosition(pContext, i0);
+ const SVec3 p1 = GetPosition(pContext, i1);
+ const SVec3 p2 = GetPosition(pContext, i2);
+ if (veq(p0,p1) || veq(p0,p2) || veq(p1,p2)) // degenerate
+ {
+ pTriInfos[t].iFlag |= MARK_DEGENERATE;
+ ++iDegenTriangles;
+ }
+ }
+ iNrTrianglesIn = iTotTris - iDegenTriangles;
+
+ // mark all triangle pairs that belong to a quad with only one
+ // good triangle. These need special treatment in DegenEpilogue().
+ // Additionally, move all good triangles to the start of
+ // pTriInfos[] and piTriListIn[] without changing order and
+ // put the degenerate triangles last.
+ DegenPrologue(pTriInfos, piTriListIn, iNrTrianglesIn, iTotTris);
+
+
+ // evaluate triangle level attributes and neighbor list
+ //printf("gen neighbors list begin\n");
+ InitTriInfo(pTriInfos, piTriListIn, pContext, iNrTrianglesIn);
+ //printf("gen neighbors list end\n");
+
+
+ // based on the 4 rules, identify groups based on connectivity
+ iNrMaxGroups = iNrTrianglesIn*3;
+ pGroups = (SGroup *) malloc(sizeof(SGroup)*iNrMaxGroups);
+ piGroupTrianglesBuffer = (int *) malloc(sizeof(int)*iNrTrianglesIn*3);
+ if (pGroups==NULL || piGroupTrianglesBuffer==NULL)
+ {
+ if (pGroups!=NULL) free(pGroups);
+ if (piGroupTrianglesBuffer!=NULL) free(piGroupTrianglesBuffer);
+ free(piTriListIn);
+ free(pTriInfos);
+ return TFALSE;
+ }
+ //printf("gen 4rule groups begin\n");
+ iNrActiveGroups =
+ Build4RuleGroups(pTriInfos, pGroups, piGroupTrianglesBuffer, piTriListIn, iNrTrianglesIn);
+ //printf("gen 4rule groups end\n");
+
+ //
+
+ psTspace = (STSpace *) malloc(sizeof(STSpace)*iNrTSPaces);
+ if (psTspace==NULL)
+ {
+ free(piTriListIn);
+ free(pTriInfos);
+ free(pGroups);
+ free(piGroupTrianglesBuffer);
+ return TFALSE;
+ }
+ memset(psTspace, 0, sizeof(STSpace)*iNrTSPaces);
+ for (t=0; t<iNrTSPaces; t++)
+ {
+ psTspace[t].vOs.x=1.0f; psTspace[t].vOs.y=0.0f; psTspace[t].vOs.z=0.0f; psTspace[t].fMagS = 1.0f;
+ psTspace[t].vOt.x=0.0f; psTspace[t].vOt.y=1.0f; psTspace[t].vOt.z=0.0f; psTspace[t].fMagT = 1.0f;
+ }
+
+ // make tspaces, each group is split up into subgroups if necessary
+ // based on fAngularThreshold. Finally a tangent space is made for
+ // every resulting subgroup
+ //printf("gen tspaces begin\n");
+ bRes = GenerateTSpaces(psTspace, pTriInfos, pGroups, iNrActiveGroups, piTriListIn, fThresCos, pContext);
+ //printf("gen tspaces end\n");
+
+ // clean up
+ free(pGroups);
+ free(piGroupTrianglesBuffer);
+
+ if (!bRes) // if an allocation in GenerateTSpaces() failed
+ {
+ // clean up and return false
+ free(pTriInfos); free(piTriListIn); free(psTspace);
+ return TFALSE;
+ }
+
+
+ // degenerate quads with one good triangle will be fixed by copying a space from
+ // the good triangle to the coinciding vertex.
+ // all other degenerate triangles will just copy a space from any good triangle
+ // with the same welded index in piTriListIn[].
+ DegenEpilogue(psTspace, pTriInfos, piTriListIn, pContext, iNrTrianglesIn, iTotTris);
+
+ free(pTriInfos); free(piTriListIn);
+
+ index = 0;
+ for (f=0; f<iNrFaces; f++)
+ {
+ const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f);
+ if (verts!=3 && verts!=4) continue;
+
+
+ // I've decided to let degenerate triangles and group-with-anythings
+ // vary between left/right hand coordinate systems at the vertices.
+ // All healthy triangles on the other hand are built to always be either or.
+
+ /*// force the coordinate system orientation to be uniform for every face.
+ // (this is already the case for good triangles but not for
+ // degenerate ones and those with bGroupWithAnything==true)
+ bool bOrient = psTspace[index].bOrient;
+ if (psTspace[index].iCounter == 0) // tspace was not derived from a group
+ {
+ // look for a space created in GenerateTSpaces() by iCounter>0
+ bool bNotFound = true;
+ int i=1;
+ while (i<verts && bNotFound)
+ {
+ if (psTspace[index+i].iCounter > 0) bNotFound=false;
+ else ++i;
+ }
+ if (!bNotFound) bOrient = psTspace[index+i].bOrient;
+ }*/
+
+ // set data
+ for (i=0; i<verts; i++)
+ {
+ const STSpace * pTSpace = &psTspace[index];
+ float tang[] = {pTSpace->vOs.x, pTSpace->vOs.y, pTSpace->vOs.z};
+ float bitang[] = {pTSpace->vOt.x, pTSpace->vOt.y, pTSpace->vOt.z};
+ if (pContext->m_pInterface->m_setTSpace!=NULL)
+ pContext->m_pInterface->m_setTSpace(pContext, tang, bitang, pTSpace->fMagS, pTSpace->fMagT, pTSpace->bOrient, f, i);
+ if (pContext->m_pInterface->m_setTSpaceBasic!=NULL)
+ pContext->m_pInterface->m_setTSpaceBasic(pContext, tang, pTSpace->bOrient==TTRUE ? 1.0f : (-1.0f), f, i);
+
+ ++index;
+ }
+ }
+
+ free(psTspace);
+
+
+ return TTRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef struct {
+ float vert[3];
+ int index;
+} STmpVert;
+
+static const int g_iCells = 2048;
+
+#ifdef _MSC_VER
+ #define NOINLINE __declspec(noinline)
+#else
+ #define NOINLINE __attribute__ ((noinline))
+#endif
+
+// it is IMPORTANT that this function is called to evaluate the hash since
+// inlining could potentially reorder instructions and generate different
+// results for the same effective input value fVal.
+static NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal)
+{
+ const float fIndex = g_iCells * ((fVal-fMin)/(fMax-fMin));
+ const int iIndex = (int)fIndex;
+ return iIndex < g_iCells ? (iIndex >= 0 ? iIndex : 0) : (g_iCells - 1);
+}
+
+static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in);
+static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries);
+static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
+
+static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
+{
+
+ // Generate bounding box
+ int * piHashTable=NULL, * piHashCount=NULL, * piHashOffsets=NULL, * piHashCount2=NULL;
+ STmpVert * pTmpVert = NULL;
+ int i=0, iChannel=0, k=0, e=0;
+ int iMaxCount=0;
+ SVec3 vMin = GetPosition(pContext, 0), vMax = vMin, vDim;
+ float fMin, fMax;
+ for (i=1; i<(iNrTrianglesIn*3); i++)
+ {
+ const int index = piTriList_in_and_out[i];
+
+ const SVec3 vP = GetPosition(pContext, index);
+ if (vMin.x > vP.x) vMin.x = vP.x;
+ else if (vMax.x < vP.x) vMax.x = vP.x;
+ if (vMin.y > vP.y) vMin.y = vP.y;
+ else if (vMax.y < vP.y) vMax.y = vP.y;
+ if (vMin.z > vP.z) vMin.z = vP.z;
+ else if (vMax.z < vP.z) vMax.z = vP.z;
+ }
+
+ vDim = vsub(vMax,vMin);
+ iChannel = 0;
+ fMin = vMin.x; fMax=vMax.x;
+ if (vDim.y>vDim.x && vDim.y>vDim.z)
+ {
+ iChannel=1;
+ fMin = vMin.y, fMax=vMax.y;
+ }
+ else if (vDim.z>vDim.x)
+ {
+ iChannel=2;
+ fMin = vMin.z, fMax=vMax.z;
+ }
+
+ // make allocations
+ piHashTable = (int *) malloc(sizeof(int)*iNrTrianglesIn*3);
+ piHashCount = (int *) malloc(sizeof(int)*g_iCells);
+ piHashOffsets = (int *) malloc(sizeof(int)*g_iCells);
+ piHashCount2 = (int *) malloc(sizeof(int)*g_iCells);
+
+ if (piHashTable==NULL || piHashCount==NULL || piHashOffsets==NULL || piHashCount2==NULL)
+ {
+ if (piHashTable!=NULL) free(piHashTable);
+ if (piHashCount!=NULL) free(piHashCount);
+ if (piHashOffsets!=NULL) free(piHashOffsets);
+ if (piHashCount2!=NULL) free(piHashCount2);
+ GenerateSharedVerticesIndexListSlow(piTriList_in_and_out, pContext, iNrTrianglesIn);
+ return;
+ }
+ memset(piHashCount, 0, sizeof(int)*g_iCells);
+ memset(piHashCount2, 0, sizeof(int)*g_iCells);
+
+ // count amount of elements in each cell unit
+ for (i=0; i<(iNrTrianglesIn*3); i++)
+ {
+ const int index = piTriList_in_and_out[i];
+ const SVec3 vP = GetPosition(pContext, index);
+ const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z);
+ const int iCell = FindGridCell(fMin, fMax, fVal);
+ ++piHashCount[iCell];
+ }
+
+ // evaluate start index of each cell.
+ piHashOffsets[0]=0;
+ for (k=1; k<g_iCells; k++)
+ piHashOffsets[k]=piHashOffsets[k-1]+piHashCount[k-1];
+
+ // insert vertices
+ for (i=0; i<(iNrTrianglesIn*3); i++)
+ {
+ const int index = piTriList_in_and_out[i];
+ const SVec3 vP = GetPosition(pContext, index);
+ const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z);
+ const int iCell = FindGridCell(fMin, fMax, fVal);
+ int * pTable = NULL;
+
+ assert(piHashCount2[iCell]<piHashCount[iCell]);
+ pTable = &piHashTable[piHashOffsets[iCell]];
+ pTable[piHashCount2[iCell]] = i; // vertex i has been inserted.
+ ++piHashCount2[iCell];
+ }
+ for (k=0; k<g_iCells; k++)
+ assert(piHashCount2[k] == piHashCount[k]); // verify the count
+ free(piHashCount2);
+
+ // find maximum amount of entries in any hash entry
+ iMaxCount = piHashCount[0];
+ for (k=1; k<g_iCells; k++)
+ if (iMaxCount<piHashCount[k])
+ iMaxCount=piHashCount[k];
+ pTmpVert = (STmpVert *) malloc(sizeof(STmpVert)*iMaxCount);
+
+
+ // complete the merge
+ for (k=0; k<g_iCells; k++)
+ {
+ // extract table of cell k and amount of entries in it
+ int * pTable = &piHashTable[piHashOffsets[k]];
+ const int iEntries = piHashCount[k];
+ if (iEntries < 2) continue;
+
+ if (pTmpVert!=NULL)
+ {
+ for (e=0; e<iEntries; e++)
+ {
+ int i = pTable[e];
+ const SVec3 vP = GetPosition(pContext, piTriList_in_and_out[i]);
+ pTmpVert[e].vert[0] = vP.x; pTmpVert[e].vert[1] = vP.y;
+ pTmpVert[e].vert[2] = vP.z; pTmpVert[e].index = i;
+ }
+ MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, 0, iEntries-1);
+ }
+ else
+ MergeVertsSlow(piTriList_in_and_out, pContext, pTable, iEntries);
+ }
+
+ if (pTmpVert!=NULL) { free(pTmpVert); }
+ free(piHashTable);
+ free(piHashCount);
+ free(piHashOffsets);
+}
+
+static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in)
+{
+ // make bbox
+ int c=0, l=0, channel=0;
+ float fvMin[3], fvMax[3];
+ float dx=0, dy=0, dz=0, fSep=0;
+ for (c=0; c<3; c++)
+ { fvMin[c]=pTmpVert[iL_in].vert[c]; fvMax[c]=fvMin[c]; }
+ for (l=(iL_in+1); l<=iR_in; l++)
+ for (c=0; c<3; c++)
+ if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].vert[c];
+ else if (fvMax[c]<pTmpVert[l].vert[c]) fvMax[c]=pTmpVert[l].vert[c];
+
+ dx = fvMax[0]-fvMin[0];
+ dy = fvMax[1]-fvMin[1];
+ dz = fvMax[2]-fvMin[2];
+
+ channel = 0;
+ if (dy>dx && dy>dz) channel=1;
+ else if (dz>dx) channel=2;
+
+ fSep = 0.5f*(fvMax[channel]+fvMin[channel]);
+
+ // terminate recursion when the separation/average value
+ // is no longer strictly between fMin and fMax values.
+ if (fSep>=fvMax[channel] || fSep<=fvMin[channel])
+ {
+ // complete the weld
+ for (l=iL_in; l<=iR_in; l++)
+ {
+ int i = pTmpVert[l].index;
+ const int index = piTriList_in_and_out[i];
+ const SVec3 vP = GetPosition(pContext, index);
+ const SVec3 vN = GetNormal(pContext, index);
+ const SVec3 vT = GetTexCoord(pContext, index);
+
+ tbool bNotFound = TTRUE;
+ int l2=iL_in, i2rec=-1;
+ while (l2<l && bNotFound)
+ {
+ const int i2 = pTmpVert[l2].index;
+ const int index2 = piTriList_in_and_out[i2];
+ const SVec3 vP2 = GetPosition(pContext, index2);
+ const SVec3 vN2 = GetNormal(pContext, index2);
+ const SVec3 vT2 = GetTexCoord(pContext, index2);
+ i2rec=i2;
+
+ //if (vP==vP2 && vN==vN2 && vT==vT2)
+ if (vP.x==vP2.x && vP.y==vP2.y && vP.z==vP2.z &&
+ vN.x==vN2.x && vN.y==vN2.y && vN.z==vN2.z &&
+ vT.x==vT2.x && vT.y==vT2.y && vT.z==vT2.z)
+ bNotFound = TFALSE;
+ else
+ ++l2;
+ }
+
+ // merge if previously found
+ if (!bNotFound)
+ piTriList_in_and_out[i] = piTriList_in_and_out[i2rec];
+ }
+ }
+ else
+ {
+ int iL=iL_in, iR=iR_in;
+ assert((iR_in-iL_in)>0); // at least 2 entries
+
+ // separate (by fSep) all points between iL_in and iR_in in pTmpVert[]
+ while (iL < iR)
+ {
+ tbool bReadyLeftSwap = TFALSE, bReadyRightSwap = TFALSE;
+ while ((!bReadyLeftSwap) && iL<iR)
+ {
+ assert(iL>=iL_in && iL<=iR_in);
+ bReadyLeftSwap = !(pTmpVert[iL].vert[channel]<fSep);
+ if (!bReadyLeftSwap) ++iL;
+ }
+ while ((!bReadyRightSwap) && iL<iR)
+ {
+ assert(iR>=iL_in && iR<=iR_in);
+ bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep;
+ if (!bReadyRightSwap) --iR;
+ }
+ assert( (iL<iR) || !(bReadyLeftSwap && bReadyRightSwap) );
+
+ if (bReadyLeftSwap && bReadyRightSwap)
+ {
+ const STmpVert sTmp = pTmpVert[iL];
+ assert(iL<iR);
+ pTmpVert[iL] = pTmpVert[iR];
+ pTmpVert[iR] = sTmp;
+ ++iL; --iR;
+ }
+ }
+
+ assert(iL==(iR+1) || (iL==iR));
+ if (iL==iR)
+ {
+ const tbool bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep;
+ if (bReadyRightSwap) ++iL;
+ else --iR;
+ }
+
+ // only need to weld when there is more than 1 instance of the (x,y,z)
+ if (iL_in < iR)
+ MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL_in, iR); // weld all left of fSep
+ if (iL < iR_in)
+ MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL, iR_in); // weld all right of (or equal to) fSep
+ }
+}
+
+static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries)
+{
+ // this can be optimized further using a tree structure or more hashing.
+ int e=0;
+ for (e=0; e<iEntries; e++)
+ {
+ int i = pTable[e];
+ const int index = piTriList_in_and_out[i];
+ const SVec3 vP = GetPosition(pContext, index);
+ const SVec3 vN = GetNormal(pContext, index);
+ const SVec3 vT = GetTexCoord(pContext, index);
+
+ tbool bNotFound = TTRUE;
+ int e2=0, i2rec=-1;
+ while (e2<e && bNotFound)
+ {
+ const int i2 = pTable[e2];
+ const int index2 = piTriList_in_and_out[i2];
+ const SVec3 vP2 = GetPosition(pContext, index2);
+ const SVec3 vN2 = GetNormal(pContext, index2);
+ const SVec3 vT2 = GetTexCoord(pContext, index2);
+ i2rec = i2;
+
+ if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2))
+ bNotFound = TFALSE;
+ else
+ ++e2;
+ }
+
+ // merge if previously found
+ if (!bNotFound)
+ piTriList_in_and_out[i] = piTriList_in_and_out[i2rec];
+ }
+}
+
+static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
+{
+ int iNumUniqueVerts = 0, t=0, i=0;
+ for (t=0; t<iNrTrianglesIn; t++)
+ {
+ for (i=0; i<3; i++)
+ {
+ const int offs = t*3 + i;
+ const int index = piTriList_in_and_out[offs];
+
+ const SVec3 vP = GetPosition(pContext, index);
+ const SVec3 vN = GetNormal(pContext, index);
+ const SVec3 vT = GetTexCoord(pContext, index);
+
+ tbool bFound = TFALSE;
+ int t2=0, index2rec=-1;
+ while (!bFound && t2<=t)
+ {
+ int j=0;
+ while (!bFound && j<3)
+ {
+ const int index2 = piTriList_in_and_out[t2*3 + j];
+ const SVec3 vP2 = GetPosition(pContext, index2);
+ const SVec3 vN2 = GetNormal(pContext, index2);
+ const SVec3 vT2 = GetTexCoord(pContext, index2);
+
+ if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2))
+ bFound = TTRUE;
+ else
+ ++j;
+ }
+ if (!bFound) ++t2;
+ }
+
+ assert(bFound);
+ // if we found our own
+ if (index2rec == index) { ++iNumUniqueVerts; }
+
+ piTriList_in_and_out[offs] = index2rec;
+ }
+ }
+}
+
+static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
+{
+ int iTSpacesOffs = 0, f=0, t=0;
+ int iDstTriIndex = 0;
+ for (f=0; f<pContext->m_pInterface->m_getNumFaces(pContext); f++)
+ {
+ const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f);
+ if (verts!=3 && verts!=4) continue;
+
+ pTriInfos[iDstTriIndex].iOrgFaceNumber = f;
+ pTriInfos[iDstTriIndex].iTSpacesOffs = iTSpacesOffs;
+
+ if (verts==3)
+ {
+ unsigned char * pVerts = pTriInfos[iDstTriIndex].vert_num;
+ pVerts[0]=0; pVerts[1]=1; pVerts[2]=2;
+ piTriList_out[iDstTriIndex*3+0] = MakeIndex(f, 0);
+ piTriList_out[iDstTriIndex*3+1] = MakeIndex(f, 1);
+ piTriList_out[iDstTriIndex*3+2] = MakeIndex(f, 2);
+ ++iDstTriIndex; // next
+ }
+ else
+ {
+ {
+ pTriInfos[iDstTriIndex+1].iOrgFaceNumber = f;
+ pTriInfos[iDstTriIndex+1].iTSpacesOffs = iTSpacesOffs;
+ }
+
+ {
+ // need an order independent way to evaluate
+ // tspace on quads. This is done by splitting
+ // along the shortest diagonal.
+ const int i0 = MakeIndex(f, 0);
+ const int i1 = MakeIndex(f, 1);
+ const int i2 = MakeIndex(f, 2);
+ const int i3 = MakeIndex(f, 3);
+ const SVec3 T0 = GetTexCoord(pContext, i0);
+ const SVec3 T1 = GetTexCoord(pContext, i1);
+ const SVec3 T2 = GetTexCoord(pContext, i2);
+ const SVec3 T3 = GetTexCoord(pContext, i3);
+ const float distSQ_02 = LengthSquared(vsub(T2,T0));
+ const float distSQ_13 = LengthSquared(vsub(T3,T1));
+ tbool bQuadDiagIs_02;
+ if (distSQ_02<distSQ_13)
+ bQuadDiagIs_02 = TTRUE;
+ else if (distSQ_13<distSQ_02)
+ bQuadDiagIs_02 = TFALSE;
+ else
+ {
+ const SVec3 P0 = GetPosition(pContext, i0);
+ const SVec3 P1 = GetPosition(pContext, i1);
+ const SVec3 P2 = GetPosition(pContext, i2);
+ const SVec3 P3 = GetPosition(pContext, i3);
+ const float distSQ_02 = LengthSquared(vsub(P2,P0));
+ const float distSQ_13 = LengthSquared(vsub(P3,P1));
+
+ bQuadDiagIs_02 = distSQ_13<distSQ_02 ? TFALSE : TTRUE;
+ }
+
+ if (bQuadDiagIs_02)
+ {
+ {
+ unsigned char * pVerts_A = pTriInfos[iDstTriIndex].vert_num;
+ pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=2;
+ }
+ piTriList_out[iDstTriIndex*3+0] = i0;
+ piTriList_out[iDstTriIndex*3+1] = i1;
+ piTriList_out[iDstTriIndex*3+2] = i2;
+ ++iDstTriIndex; // next
+ {
+ unsigned char * pVerts_B = pTriInfos[iDstTriIndex].vert_num;
+ pVerts_B[0]=0; pVerts_B[1]=2; pVerts_B[2]=3;
+ }
+ piTriList_out[iDstTriIndex*3+0] = i0;
+ piTriList_out[iDstTriIndex*3+1] = i2;
+ piTriList_out[iDstTriIndex*3+2] = i3;
+ ++iDstTriIndex; // next
+ }
+ else
+ {
+ {
+ unsigned char * pVerts_A = pTriInfos[iDstTriIndex].vert_num;
+ pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=3;
+ }
+ piTriList_out[iDstTriIndex*3+0] = i0;
+ piTriList_out[iDstTriIndex*3+1] = i1;
+ piTriList_out[iDstTriIndex*3+2] = i3;
+ ++iDstTriIndex; // next
+ {
+ unsigned char * pVerts_B = pTriInfos[iDstTriIndex].vert_num;
+ pVerts_B[0]=1; pVerts_B[1]=2; pVerts_B[2]=3;
+ }
+ piTriList_out[iDstTriIndex*3+0] = i1;
+ piTriList_out[iDstTriIndex*3+1] = i2;
+ piTriList_out[iDstTriIndex*3+2] = i3;
+ ++iDstTriIndex; // next
+ }
+ }
+ }
+
+ iTSpacesOffs += verts;
+ assert(iDstTriIndex<=iNrTrianglesIn);
+ }
+
+ for (t=0; t<iNrTrianglesIn; t++)
+ pTriInfos[t].iFlag = 0;
+
+ // return total amount of tspaces
+ return iTSpacesOffs;
+}
+
+static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index)
+{
+ int iF, iI;
+ SVec3 res; float pos[3];
+ IndexToData(&iF, &iI, index);
+ pContext->m_pInterface->m_getPosition(pContext, pos, iF, iI);
+ res.x=pos[0]; res.y=pos[1]; res.z=pos[2];
+ return res;
+}
+
+static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index)
+{
+ int iF, iI;
+ SVec3 res; float norm[3];
+ IndexToData(&iF, &iI, index);
+ pContext->m_pInterface->m_getNormal(pContext, norm, iF, iI);
+ res.x=norm[0]; res.y=norm[1]; res.z=norm[2];
+ return res;
+}
+
+static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index)
+{
+ int iF, iI;
+ SVec3 res; float texc[2];
+ IndexToData(&iF, &iI, index);
+ pContext->m_pInterface->m_getTexCoord(pContext, texc, iF, iI);
+ res.x=texc[0]; res.y=texc[1]; res.z=1.0f;
+ return res;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef union {
+ struct
+ {
+ int i0, i1, f;
+ };
+ int array[3];
+} SEdge;
+
+static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn);
+static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn);
+
+// returns the texture area times 2
+static float CalcTexArea(const SMikkTSpaceContext * pContext, const int indices[])
+{
+ const SVec3 t1 = GetTexCoord(pContext, indices[0]);
+ const SVec3 t2 = GetTexCoord(pContext, indices[1]);
+ const SVec3 t3 = GetTexCoord(pContext, indices[2]);
+
+ const float t21x = t2.x-t1.x;
+ const float t21y = t2.y-t1.y;
+ const float t31x = t3.x-t1.x;
+ const float t31y = t3.y-t1.y;
+
+ const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x;
+
+ return fSignedAreaSTx2<0 ? (-fSignedAreaSTx2) : fSignedAreaSTx2;
+}
+
+static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
+{
+ int f=0, i=0, t=0;
+ // pTriInfos[f].iFlag is cleared in GenerateInitialVerticesIndexList() which is called before this function.
+
+ // generate neighbor info list
+ for (f=0; f<iNrTrianglesIn; f++)
+ for (i=0; i<3; i++)
+ {
+ pTriInfos[f].FaceNeighbors[i] = -1;
+ pTriInfos[f].AssignedGroup[i] = NULL;
+
+ pTriInfos[f].vOs.x=0.0f; pTriInfos[f].vOs.y=0.0f; pTriInfos[f].vOs.z=0.0f;
+ pTriInfos[f].vOt.x=0.0f; pTriInfos[f].vOt.y=0.0f; pTriInfos[f].vOt.z=0.0f;
+ pTriInfos[f].fMagS = 0;
+ pTriInfos[f].fMagT = 0;
+
+ // assumed bad
+ pTriInfos[f].iFlag |= GROUP_WITH_ANY;
+ }
+
+ // evaluate first order derivatives
+ for (f=0; f<iNrTrianglesIn; f++)
+ {
+ // initial values
+ const SVec3 v1 = GetPosition(pContext, piTriListIn[f*3+0]);
+ const SVec3 v2 = GetPosition(pContext, piTriListIn[f*3+1]);
+ const SVec3 v3 = GetPosition(pContext, piTriListIn[f*3+2]);
+ const SVec3 t1 = GetTexCoord(pContext, piTriListIn[f*3+0]);
+ const SVec3 t2 = GetTexCoord(pContext, piTriListIn[f*3+1]);
+ const SVec3 t3 = GetTexCoord(pContext, piTriListIn[f*3+2]);
+
+ const float t21x = t2.x-t1.x;
+ const float t21y = t2.y-t1.y;
+ const float t31x = t3.x-t1.x;
+ const float t31y = t3.y-t1.y;
+ const SVec3 d1 = vsub(v2,v1);
+ const SVec3 d2 = vsub(v3,v1);
+
+ const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x;
+ //assert(fSignedAreaSTx2!=0);
+ SVec3 vOs = vsub(vscale(t31y,d1), vscale(t21y,d2)); // eq 18
+ SVec3 vOt = vadd(vscale(-t31x,d1), vscale(t21x,d2)); // eq 19
+
+ pTriInfos[f].iFlag |= (fSignedAreaSTx2>0 ? ORIENT_PRESERVING : 0);
+
+ if ( NotZero(fSignedAreaSTx2) )
+ {
+ const float fAbsArea = fabsf(fSignedAreaSTx2);
+ const float fLenOs = Length(vOs);
+ const float fLenOt = Length(vOt);
+ const float fS = (pTriInfos[f].iFlag&ORIENT_PRESERVING)==0 ? (-1.0f) : 1.0f;
+ if ( NotZero(fLenOs) ) pTriInfos[f].vOs = vscale(fS/fLenOs, vOs);
+ if ( NotZero(fLenOt) ) pTriInfos[f].vOt = vscale(fS/fLenOt, vOt);
+
+ // evaluate magnitudes prior to normalization of vOs and vOt
+ pTriInfos[f].fMagS = fLenOs / fAbsArea;
+ pTriInfos[f].fMagT = fLenOt / fAbsArea;
+
+ // if this is a good triangle
+ if ( NotZero(pTriInfos[f].fMagS) && NotZero(pTriInfos[f].fMagT))
+ pTriInfos[f].iFlag &= (~GROUP_WITH_ANY);
+ }
+ }
+
+ // force otherwise healthy quads to a fixed orientation
+ while (t<(iNrTrianglesIn-1))
+ {
+ const int iFO_a = pTriInfos[t].iOrgFaceNumber;
+ const int iFO_b = pTriInfos[t+1].iOrgFaceNumber;
+ if (iFO_a==iFO_b) // this is a quad
+ {
+ const tbool bIsDeg_a = (pTriInfos[t].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE;
+ const tbool bIsDeg_b = (pTriInfos[t+1].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE;
+
+ // bad triangles should already have been removed by
+ // DegenPrologue(), but just in case check bIsDeg_a and bIsDeg_a are false
+ if ((bIsDeg_a||bIsDeg_b)==TFALSE)
+ {
+ const tbool bOrientA = (pTriInfos[t].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
+ const tbool bOrientB = (pTriInfos[t+1].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
+ // if this happens the quad has extremely bad mapping!!
+ if (bOrientA!=bOrientB)
+ {
+ //printf("found quad with bad mapping\n");
+ tbool bChooseOrientFirstTri = TFALSE;
+ if ((pTriInfos[t+1].iFlag&GROUP_WITH_ANY)!=0) bChooseOrientFirstTri = TTRUE;
+ else if ( CalcTexArea(pContext, &piTriListIn[t*3+0]) >= CalcTexArea(pContext, &piTriListIn[(t+1)*3+0]) )
+ bChooseOrientFirstTri = TTRUE;
+
+ // force match
+ {
+ const int t0 = bChooseOrientFirstTri ? t : (t+1);
+ const int t1 = bChooseOrientFirstTri ? (t+1) : t;
+ pTriInfos[t1].iFlag &= (~ORIENT_PRESERVING); // clear first
+ pTriInfos[t1].iFlag |= (pTriInfos[t0].iFlag&ORIENT_PRESERVING); // copy bit
+ }
+ }
+ }
+ t += 2;
+ }
+ else
+ ++t;
+ }
+
+ // match up edge pairs
+ {
+ SEdge * pEdges = (SEdge *) malloc(sizeof(SEdge)*iNrTrianglesIn*3);
+ if (pEdges==NULL)
+ BuildNeighborsSlow(pTriInfos, piTriListIn, iNrTrianglesIn);
+ else
+ {
+ BuildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn);
+
+ free(pEdges);
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int iMyTriIndex, SGroup * pGroup);
+static void AddTriToGroup(SGroup * pGroup, const int iTriIndex);
+
+static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn)
+{
+ const int iNrMaxGroups = iNrTrianglesIn*3;
+ int iNrActiveGroups = 0;
+ int iOffset = 0, f=0, i=0;
+ (void)iNrMaxGroups; /* quiet warnings in non debug mode */
+ for (f=0; f<iNrTrianglesIn; f++)
+ {
+ for (i=0; i<3; i++)
+ {
+ // if not assigned to a group
+ if ((pTriInfos[f].iFlag&GROUP_WITH_ANY)==0 && pTriInfos[f].AssignedGroup[i]==NULL)
+ {
+ tbool bOrPre;
+ int neigh_indexL, neigh_indexR;
+ const int vert_index = piTriListIn[f*3+i];
+ assert(iNrActiveGroups<iNrMaxGroups);
+ pTriInfos[f].AssignedGroup[i] = &pGroups[iNrActiveGroups];
+ pTriInfos[f].AssignedGroup[i]->iVertexRepresentitive = vert_index;
+ pTriInfos[f].AssignedGroup[i]->bOrientPreservering = (pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0;
+ pTriInfos[f].AssignedGroup[i]->iNrFaces = 0;
+ pTriInfos[f].AssignedGroup[i]->pFaceIndices = &piGroupTrianglesBuffer[iOffset];
+ ++iNrActiveGroups;
+
+ AddTriToGroup(pTriInfos[f].AssignedGroup[i], f);
+ bOrPre = (pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
+ neigh_indexL = pTriInfos[f].FaceNeighbors[i];
+ neigh_indexR = pTriInfos[f].FaceNeighbors[i>0?(i-1):2];
+ if (neigh_indexL>=0) // neighbor
+ {
+ const tbool bAnswer =
+ AssignRecur(piTriListIn, pTriInfos, neigh_indexL,
+ pTriInfos[f].AssignedGroup[i] );
+
+ const tbool bOrPre2 = (pTriInfos[neigh_indexL].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
+ const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE;
+ assert(bAnswer || bDiff);
+ (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */
+ }
+ if (neigh_indexR>=0) // neighbor
+ {
+ const tbool bAnswer =
+ AssignRecur(piTriListIn, pTriInfos, neigh_indexR,
+ pTriInfos[f].AssignedGroup[i] );
+
+ const tbool bOrPre2 = (pTriInfos[neigh_indexR].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
+ const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE;
+ assert(bAnswer || bDiff);
+ (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */
+ }
+
+ // update offset
+ iOffset += pTriInfos[f].AssignedGroup[i]->iNrFaces;
+ // since the groups are disjoint a triangle can never
+ // belong to more than 3 groups. Subsequently something
+ // is completely screwed if this assertion ever hits.
+ assert(iOffset <= iNrMaxGroups);
+ }
+ }
+ }
+
+ return iNrActiveGroups;
+}
+
+static void AddTriToGroup(SGroup * pGroup, const int iTriIndex)
+{
+ pGroup->pFaceIndices[pGroup->iNrFaces] = iTriIndex;
+ ++pGroup->iNrFaces;
+}
+
+static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[],
+ const int iMyTriIndex, SGroup * pGroup)
+{
+ STriInfo * pMyTriInfo = &psTriInfos[iMyTriIndex];
+
+ // track down vertex
+ const int iVertRep = pGroup->iVertexRepresentitive;
+ const int * pVerts = &piTriListIn[3*iMyTriIndex+0];
+ int i=-1;
+ if (pVerts[0]==iVertRep) i=0;
+ else if (pVerts[1]==iVertRep) i=1;
+ else if (pVerts[2]==iVertRep) i=2;
+ assert(i>=0 && i<3);
+
+ // early out
+ if (pMyTriInfo->AssignedGroup[i] == pGroup) return TTRUE;
+ else if (pMyTriInfo->AssignedGroup[i]!=NULL) return TFALSE;
+ if ((pMyTriInfo->iFlag&GROUP_WITH_ANY)!=0)
+ {
+ // first to group with a group-with-anything triangle
+ // determines it's orientation.
+ // This is the only existing order dependency in the code!!
+ if ( pMyTriInfo->AssignedGroup[0] == NULL &&
+ pMyTriInfo->AssignedGroup[1] == NULL &&
+ pMyTriInfo->AssignedGroup[2] == NULL )
+ {
+ pMyTriInfo->iFlag &= (~ORIENT_PRESERVING);
+ pMyTriInfo->iFlag |= (pGroup->bOrientPreservering ? ORIENT_PRESERVING : 0);
+ }
+ }
+ {
+ const tbool bOrient = (pMyTriInfo->iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE;
+ if (bOrient != pGroup->bOrientPreservering) return TFALSE;
+ }
+
+ AddTriToGroup(pGroup, iMyTriIndex);
+ pMyTriInfo->AssignedGroup[i] = pGroup;
+
+ {
+ const int neigh_indexL = pMyTriInfo->FaceNeighbors[i];
+ const int neigh_indexR = pMyTriInfo->FaceNeighbors[i>0?(i-1):2];
+ if (neigh_indexL>=0)
+ AssignRecur(piTriListIn, psTriInfos, neigh_indexL, pGroup);
+ if (neigh_indexR>=0)
+ AssignRecur(piTriListIn, psTriInfos, neigh_indexR, pGroup);
+ }
+
+
+
+ return TTRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2);
+static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed);
+static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext * pContext, const int iVertexRepresentitive);
+
+static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[],
+ const int iNrActiveGroups, const int piTriListIn[], const float fThresCos,
+ const SMikkTSpaceContext * pContext)
+{
+ STSpace * pSubGroupTspace = NULL;
+ SSubGroup * pUniSubGroups = NULL;
+ int * pTmpMembers = NULL;
+ int iMaxNrFaces=0, iUniqueTspaces=0, g=0, i=0;
+ for (g=0; g<iNrActiveGroups; g++)
+ if (iMaxNrFaces < pGroups[g].iNrFaces)
+ iMaxNrFaces = pGroups[g].iNrFaces;
+
+ if (iMaxNrFaces == 0) return TTRUE;
+
+ // make initial allocations
+ pSubGroupTspace = (STSpace *) malloc(sizeof(STSpace)*iMaxNrFaces);
+ pUniSubGroups = (SSubGroup *) malloc(sizeof(SSubGroup)*iMaxNrFaces);
+ pTmpMembers = (int *) malloc(sizeof(int)*iMaxNrFaces);
+ if (pSubGroupTspace==NULL || pUniSubGroups==NULL || pTmpMembers==NULL)
+ {
+ if (pSubGroupTspace!=NULL) free(pSubGroupTspace);
+ if (pUniSubGroups!=NULL) free(pUniSubGroups);
+ if (pTmpMembers!=NULL) free(pTmpMembers);
+ return TFALSE;
+ }
+
+
+ iUniqueTspaces = 0;
+ for (g=0; g<iNrActiveGroups; g++)
+ {
+ const SGroup * pGroup = &pGroups[g];
+ int iUniqueSubGroups = 0, s=0;
+
+ for (i=0; i<pGroup->iNrFaces; i++) // triangles
+ {
+ const int f = pGroup->pFaceIndices[i]; // triangle number
+ int index=-1, iVertIndex=-1, iOF_1=-1, iMembers=0, j=0, l=0;
+ SSubGroup tmp_group;
+ tbool bFound;
+ SVec3 n, vOs, vOt;
+ if (pTriInfos[f].AssignedGroup[0]==pGroup) index=0;
+ else if (pTriInfos[f].AssignedGroup[1]==pGroup) index=1;
+ else if (pTriInfos[f].AssignedGroup[2]==pGroup) index=2;
+ assert(index>=0 && index<3);
+
+ iVertIndex = piTriListIn[f*3+index];
+ assert(iVertIndex==pGroup->iVertexRepresentitive);
+
+ // is normalized already
+ n = GetNormal(pContext, iVertIndex);
+
+ // project
+ vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n));
+ vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n));
+ if ( VNotZero(vOs) ) vOs = Normalize(vOs);
+ if ( VNotZero(vOt) ) vOt = Normalize(vOt);
+
+ // original face number
+ iOF_1 = pTriInfos[f].iOrgFaceNumber;
+
+ iMembers = 0;
+ for (j=0; j<pGroup->iNrFaces; j++)
+ {
+ const int t = pGroup->pFaceIndices[j]; // triangle number
+ const int iOF_2 = pTriInfos[t].iOrgFaceNumber;
+
+ // project
+ SVec3 vOs2 = vsub(pTriInfos[t].vOs, vscale(vdot(n,pTriInfos[t].vOs), n));
+ SVec3 vOt2 = vsub(pTriInfos[t].vOt, vscale(vdot(n,pTriInfos[t].vOt), n));
+ if ( VNotZero(vOs2) ) vOs2 = Normalize(vOs2);
+ if ( VNotZero(vOt2) ) vOt2 = Normalize(vOt2);
+
+ {
+ const tbool bAny = ( (pTriInfos[f].iFlag | pTriInfos[t].iFlag) & GROUP_WITH_ANY )!=0 ? TTRUE : TFALSE;
+ // make sure triangles which belong to the same quad are joined.
+ const tbool bSameOrgFace = iOF_1==iOF_2 ? TTRUE : TFALSE;
+
+ const float fCosS = vdot(vOs,vOs2);
+ const float fCosT = vdot(vOt,vOt2);
+
+ assert(f!=t || bSameOrgFace); // sanity check
+ if (bAny || bSameOrgFace || (fCosS>fThresCos && fCosT>fThresCos))
+ pTmpMembers[iMembers++] = t;
+ }
+ }
+
+ // sort pTmpMembers
+ tmp_group.iNrFaces = iMembers;
+ tmp_group.pTriMembers = pTmpMembers;
+ if (iMembers>1)
+ {
+ unsigned int uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed?
+ QuickSort(pTmpMembers, 0, iMembers-1, uSeed);
+ }
+
+ // look for an existing match
+ bFound = TFALSE;
+ l=0;
+ while (l<iUniqueSubGroups && !bFound)
+ {
+ bFound = CompareSubGroups(&tmp_group, &pUniSubGroups[l]);
+ if (!bFound) ++l;
+ }
+
+ // assign tangent space index
+ assert(bFound || l==iUniqueSubGroups);
+ //piTempTangIndices[f*3+index] = iUniqueTspaces+l;
+
+ // if no match was found we allocate a new subgroup
+ if (!bFound)
+ {
+ // insert new subgroup
+ int * pIndices = (int *) malloc(sizeof(int)*iMembers);
+ if (pIndices==NULL)
+ {
+ // clean up and return false
+ int s=0;
+ for (s=0; s<iUniqueSubGroups; s++)
+ free(pUniSubGroups[s].pTriMembers);
+ free(pUniSubGroups);
+ free(pTmpMembers);
+ free(pSubGroupTspace);
+ return TFALSE;
+ }
+ pUniSubGroups[iUniqueSubGroups].iNrFaces = iMembers;
+ pUniSubGroups[iUniqueSubGroups].pTriMembers = pIndices;
+ memcpy(pIndices, tmp_group.pTriMembers, iMembers*sizeof(int));
+ pSubGroupTspace[iUniqueSubGroups] =
+ EvalTspace(tmp_group.pTriMembers, iMembers, piTriListIn, pTriInfos, pContext, pGroup->iVertexRepresentitive);
+ ++iUniqueSubGroups;
+ }
+
+ // output tspace
+ {
+ const int iOffs = pTriInfos[f].iTSpacesOffs;
+ const int iVert = pTriInfos[f].vert_num[index];
+ STSpace * pTS_out = &psTspace[iOffs+iVert];
+ assert(pTS_out->iCounter<2);
+ assert(((pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0) == pGroup->bOrientPreservering);
+ if (pTS_out->iCounter==1)
+ {
+ *pTS_out = AvgTSpace(pTS_out, &pSubGroupTspace[l]);
+ pTS_out->iCounter = 2; // update counter
+ pTS_out->bOrient = pGroup->bOrientPreservering;
+ }
+ else
+ {
+ assert(pTS_out->iCounter==0);
+ *pTS_out = pSubGroupTspace[l];
+ pTS_out->iCounter = 1; // update counter
+ pTS_out->bOrient = pGroup->bOrientPreservering;
+ }
+ }
+ }
+
+ // clean up and offset iUniqueTspaces
+ for (s=0; s<iUniqueSubGroups; s++)
+ free(pUniSubGroups[s].pTriMembers);
+ iUniqueTspaces += iUniqueSubGroups;
+ }
+
+ // clean up
+ free(pUniSubGroups);
+ free(pTmpMembers);
+ free(pSubGroupTspace);
+
+ return TTRUE;
+}
+
+static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[],
+ const SMikkTSpaceContext * pContext, const int iVertexRepresentitive)
+{
+ STSpace res;
+ float fAngleSum = 0;
+ int face=0;
+ res.vOs.x=0.0f; res.vOs.y=0.0f; res.vOs.z=0.0f;
+ res.vOt.x=0.0f; res.vOt.y=0.0f; res.vOt.z=0.0f;
+ res.fMagS = 0; res.fMagT = 0;
+
+ for (face=0; face<iFaces; face++)
+ {
+ const int f = face_indices[face];
+
+ // only valid triangles get to add their contribution
+ if ( (pTriInfos[f].iFlag&GROUP_WITH_ANY)==0 )
+ {
+ SVec3 n, vOs, vOt, p0, p1, p2, v1, v2;
+ float fCos, fAngle, fMagS, fMagT;
+ int i=-1, index=-1, i0=-1, i1=-1, i2=-1;
+ if (piTriListIn[3*f+0]==iVertexRepresentitive) i=0;
+ else if (piTriListIn[3*f+1]==iVertexRepresentitive) i=1;
+ else if (piTriListIn[3*f+2]==iVertexRepresentitive) i=2;
+ assert(i>=0 && i<3);
+
+ // project
+ index = piTriListIn[3*f+i];
+ n = GetNormal(pContext, index);
+ vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n));
+ vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n));
+ if ( VNotZero(vOs) ) vOs = Normalize(vOs);
+ if ( VNotZero(vOt) ) vOt = Normalize(vOt);
+
+ i2 = piTriListIn[3*f + (i<2?(i+1):0)];
+ i1 = piTriListIn[3*f + i];
+ i0 = piTriListIn[3*f + (i>0?(i-1):2)];
+
+ p0 = GetPosition(pContext, i0);
+ p1 = GetPosition(pContext, i1);
+ p2 = GetPosition(pContext, i2);
+ v1 = vsub(p0,p1);
+ v2 = vsub(p2,p1);
+
+ // project
+ v1 = vsub(v1, vscale(vdot(n,v1),n)); if ( VNotZero(v1) ) v1 = Normalize(v1);
+ v2 = vsub(v2, vscale(vdot(n,v2),n)); if ( VNotZero(v2) ) v2 = Normalize(v2);
+
+ // weight contribution by the angle
+ // between the two edge vectors
+ fCos = vdot(v1,v2); fCos=fCos>1?1:(fCos<(-1) ? (-1) : fCos);
+ fAngle = (float) acos(fCos);
+ fMagS = pTriInfos[f].fMagS;
+ fMagT = pTriInfos[f].fMagT;
+
+ res.vOs=vadd(res.vOs, vscale(fAngle,vOs));
+ res.vOt=vadd(res.vOt,vscale(fAngle,vOt));
+ res.fMagS+=(fAngle*fMagS);
+ res.fMagT+=(fAngle*fMagT);
+ fAngleSum += fAngle;
+ }
+ }
+
+ // normalize
+ if ( VNotZero(res.vOs) ) res.vOs = Normalize(res.vOs);
+ if ( VNotZero(res.vOt) ) res.vOt = Normalize(res.vOt);
+ if (fAngleSum>0)
+ {
+ res.fMagS /= fAngleSum;
+ res.fMagT /= fAngleSum;
+ }
+
+ return res;
+}
+
+static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2)
+{
+ tbool bStillSame=TTRUE;
+ int i=0;
+ if (pg1->iNrFaces!=pg2->iNrFaces) return TFALSE;
+ while (i<pg1->iNrFaces && bStillSame)
+ {
+ bStillSame = pg1->pTriMembers[i]==pg2->pTriMembers[i] ? TTRUE : TFALSE;
+ if (bStillSame) ++i;
+ }
+ return bStillSame;
+}
+
+static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed)
+{
+ int iL, iR, n, index, iMid, iTmp;
+
+ // Random
+ unsigned int t=uSeed&31;
+ t=(uSeed<<t)|(uSeed>>(32-t));
+ uSeed=uSeed+t+3;
+ // Random end
+
+ iL=iLeft; iR=iRight;
+ n = (iR-iL)+1;
+ assert(n>=0);
+ index = (int) (uSeed%n);
+
+ iMid=pSortBuffer[index + iL];
+
+
+ do
+ {
+ while (pSortBuffer[iL] < iMid)
+ ++iL;
+ while (pSortBuffer[iR] > iMid)
+ --iR;
+
+ if (iL <= iR)
+ {
+ iTmp = pSortBuffer[iL];
+ pSortBuffer[iL] = pSortBuffer[iR];
+ pSortBuffer[iR] = iTmp;
+ ++iL; --iR;
+ }
+ }
+ while (iL <= iR);
+
+ if (iLeft < iR)
+ QuickSort(pSortBuffer, iLeft, iR, uSeed);
+ if (iL < iRight)
+ QuickSort(pSortBuffer, iL, iRight, uSeed);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed);
+static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in);
+
+static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn)
+{
+ // build array of edges
+ unsigned int uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed?
+ int iEntries=0, iCurStartIndex=-1, f=0, i=0;
+ for (f=0; f<iNrTrianglesIn; f++)
+ for (i=0; i<3; i++)
+ {
+ const int i0 = piTriListIn[f*3+i];
+ const int i1 = piTriListIn[f*3+(i<2?(i+1):0)];
+ pEdges[f*3+i].i0 = i0 < i1 ? i0 : i1; // put minimum index in i0
+ pEdges[f*3+i].i1 = !(i0 < i1) ? i0 : i1; // put maximum index in i1
+ pEdges[f*3+i].f = f; // record face number
+ }
+
+ // sort over all edges by i0, this is the pricy one.
+ QuickSortEdges(pEdges, 0, iNrTrianglesIn*3-1, 0, uSeed); // sort channel 0 which is i0
+
+ // sub sort over i1, should be fast.
+ // could replace this with a 64 bit int sort over (i0,i1)
+ // with i0 as msb in the quicksort call above.
+ iEntries = iNrTrianglesIn*3;
+ iCurStartIndex = 0;
+ for (i=1; i<iEntries; i++)
+ {
+ if (pEdges[iCurStartIndex].i0 != pEdges[i].i0)
+ {
+ const int iL = iCurStartIndex;
+ const int iR = i-1;
+ //const int iElems = i-iL;
+ iCurStartIndex = i;
+ QuickSortEdges(pEdges, iL, iR, 1, uSeed); // sort channel 1 which is i1
+ }
+ }
+
+ // sub sort over f, which should be fast.
+ // this step is to remain compliant with BuildNeighborsSlow() when
+ // more than 2 triangles use the same edge (such as a butterfly topology).
+ iCurStartIndex = 0;
+ for (i=1; i<iEntries; i++)
+ {
+ if (pEdges[iCurStartIndex].i0 != pEdges[i].i0 || pEdges[iCurStartIndex].i1 != pEdges[i].i1)
+ {
+ const int iL = iCurStartIndex;
+ const int iR = i-1;
+ //const int iElems = i-iL;
+ iCurStartIndex = i;
+ QuickSortEdges(pEdges, iL, iR, 2, uSeed); // sort channel 2 which is f
+ }
+ }
+
+ // pair up, adjacent triangles
+ for (i=0; i<iEntries; i++)
+ {
+ const int i0=pEdges[i].i0;
+ const int i1=pEdges[i].i1;
+ const int f = pEdges[i].f;
+ tbool bUnassigned_A;
+
+ int i0_A, i1_A;
+ int edgenum_A, edgenum_B=0; // 0,1 or 2
+ GetEdge(&i0_A, &i1_A, &edgenum_A, &piTriListIn[f*3], i0, i1); // resolve index ordering and edge_num
+ bUnassigned_A = pTriInfos[f].FaceNeighbors[edgenum_A] == -1 ? TTRUE : TFALSE;
+
+ if (bUnassigned_A)
+ {
+ // get true index ordering
+ int j=i+1, t;
+ tbool bNotFound = TTRUE;
+ while (j<iEntries && i0==pEdges[j].i0 && i1==pEdges[j].i1 && bNotFound)
+ {
+ tbool bUnassigned_B;
+ int i0_B, i1_B;
+ t = pEdges[j].f;
+ // flip i0_B and i1_B
+ GetEdge(&i1_B, &i0_B, &edgenum_B, &piTriListIn[t*3], pEdges[j].i0, pEdges[j].i1); // resolve index ordering and edge_num
+ //assert(!(i0_A==i1_B && i1_A==i0_B));
+ bUnassigned_B = pTriInfos[t].FaceNeighbors[edgenum_B]==-1 ? TTRUE : TFALSE;
+ if (i0_A==i0_B && i1_A==i1_B && bUnassigned_B)
+ bNotFound = TFALSE;
+ else
+ ++j;
+ }
+
+ if (!bNotFound)
+ {
+ int t = pEdges[j].f;
+ pTriInfos[f].FaceNeighbors[edgenum_A] = t;
+ //assert(pTriInfos[t].FaceNeighbors[edgenum_B]==-1);
+ pTriInfos[t].FaceNeighbors[edgenum_B] = f;
+ }
+ }
+ }
+}
+
+static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn)
+{
+ int f=0, i=0;
+ for (f=0; f<iNrTrianglesIn; f++)
+ {
+ for (i=0; i<3; i++)
+ {
+ // if unassigned
+ if (pTriInfos[f].FaceNeighbors[i] == -1)
+ {
+ const int i0_A = piTriListIn[f*3+i];
+ const int i1_A = piTriListIn[f*3+(i<2?(i+1):0)];
+
+ // search for a neighbor
+ tbool bFound = TFALSE;
+ int t=0, j=0;
+ while (!bFound && t<iNrTrianglesIn)
+ {
+ if (t!=f)
+ {
+ j=0;
+ while (!bFound && j<3)
+ {
+ // in rev order
+ const int i1_B = piTriListIn[t*3+j];
+ const int i0_B = piTriListIn[t*3+(j<2?(j+1):0)];
+ //assert(!(i0_A==i1_B && i1_A==i0_B));
+ if (i0_A==i0_B && i1_A==i1_B)
+ bFound = TTRUE;
+ else
+ ++j;
+ }
+ }
+
+ if (!bFound) ++t;
+ }
+
+ // assign neighbors
+ if (bFound)
+ {
+ pTriInfos[f].FaceNeighbors[i] = t;
+ //assert(pTriInfos[t].FaceNeighbors[j]==-1);
+ pTriInfos[t].FaceNeighbors[j] = f;
+ }
+ }
+ }
+ }
+}
+
+static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed)
+{
+ unsigned int t;
+ int iL, iR, n, index, iMid;
+
+ // early out
+ SEdge sTmp;
+ const int iElems = iRight-iLeft+1;
+ if (iElems<2) return;
+ else if (iElems==2)
+ {
+ if (pSortBuffer[iLeft].array[channel] > pSortBuffer[iRight].array[channel])
+ {
+ sTmp = pSortBuffer[iLeft];
+ pSortBuffer[iLeft] = pSortBuffer[iRight];
+ pSortBuffer[iRight] = sTmp;
+ }
+ return;
+ }
+
+ // Random
+ t=uSeed&31;
+ t=(uSeed<<t)|(uSeed>>(32-t));
+ uSeed=uSeed+t+3;
+ // Random end
+
+ iL=iLeft, iR=iRight;
+ n = (iR-iL)+1;
+ assert(n>=0);
+ index = (int) (uSeed%n);
+
+ iMid=pSortBuffer[index + iL].array[channel];
+
+ do
+ {
+ while (pSortBuffer[iL].array[channel] < iMid)
+ ++iL;
+ while (pSortBuffer[iR].array[channel] > iMid)
+ --iR;
+
+ if (iL <= iR)
+ {
+ sTmp = pSortBuffer[iL];
+ pSortBuffer[iL] = pSortBuffer[iR];
+ pSortBuffer[iR] = sTmp;
+ ++iL; --iR;
+ }
+ }
+ while (iL <= iR);
+
+ if (iLeft < iR)
+ QuickSortEdges(pSortBuffer, iLeft, iR, channel, uSeed);
+ if (iL < iRight)
+ QuickSortEdges(pSortBuffer, iL, iRight, channel, uSeed);
+}
+
+// resolve ordering and edge number
+static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in)
+{
+ *edgenum_out = -1;
+
+ // test if first index is on the edge
+ if (indices[0]==i0_in || indices[0]==i1_in)
+ {
+ // test if second index is on the edge
+ if (indices[1]==i0_in || indices[1]==i1_in)
+ {
+ edgenum_out[0]=0; // first edge
+ i0_out[0]=indices[0];
+ i1_out[0]=indices[1];
+ }
+ else
+ {
+ edgenum_out[0]=2; // third edge
+ i0_out[0]=indices[2];
+ i1_out[0]=indices[0];
+ }
+ }
+ else
+ {
+ // only second and third index is on the edge
+ edgenum_out[0]=1; // second edge
+ i0_out[0]=indices[1];
+ i1_out[0]=indices[2];
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Degenerate triangles ////////////////////////////////////
+
+static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris)
+{
+ int iNextGoodTriangleSearchIndex=-1;
+ tbool bStillFindingGoodOnes;
+
+ // locate quads with only one good triangle
+ int t=0;
+ while (t<(iTotTris-1))
+ {
+ const int iFO_a = pTriInfos[t].iOrgFaceNumber;
+ const int iFO_b = pTriInfos[t+1].iOrgFaceNumber;
+ if (iFO_a==iFO_b) // this is a quad
+ {
+ const tbool bIsDeg_a = (pTriInfos[t].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE;
+ const tbool bIsDeg_b = (pTriInfos[t+1].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE;
+ if ((bIsDeg_a^bIsDeg_b)!=0)
+ {
+ pTriInfos[t].iFlag |= QUAD_ONE_DEGEN_TRI;
+ pTriInfos[t+1].iFlag |= QUAD_ONE_DEGEN_TRI;
+ }
+ t += 2;
+ }
+ else
+ ++t;
+ }
+
+ // reorder list so all degen triangles are moved to the back
+ // without reordering the good triangles
+ iNextGoodTriangleSearchIndex = 1;
+ t=0;
+ bStillFindingGoodOnes = TTRUE;
+ while (t<iNrTrianglesIn && bStillFindingGoodOnes)
+ {
+ const tbool bIsGood = (pTriInfos[t].iFlag&MARK_DEGENERATE)==0 ? TTRUE : TFALSE;
+ if (bIsGood)
+ {
+ if (iNextGoodTriangleSearchIndex < (t+2))
+ iNextGoodTriangleSearchIndex = t+2;
+ }
+ else
+ {
+ int t0, t1;
+ // search for the first good triangle.
+ tbool bJustADegenerate = TTRUE;
+ while (bJustADegenerate && iNextGoodTriangleSearchIndex<iTotTris)
+ {
+ const tbool bIsGood = (pTriInfos[iNextGoodTriangleSearchIndex].iFlag&MARK_DEGENERATE)==0 ? TTRUE : TFALSE;
+ if (bIsGood) bJustADegenerate=TFALSE;
+ else ++iNextGoodTriangleSearchIndex;
+ }
+
+ t0 = t;
+ t1 = iNextGoodTriangleSearchIndex;
+ ++iNextGoodTriangleSearchIndex;
+ assert(iNextGoodTriangleSearchIndex > (t+1));
+
+ // swap triangle t0 and t1
+ if (!bJustADegenerate)
+ {
+ int i=0;
+ for (i=0; i<3; i++)
+ {
+ const int index = piTriList_out[t0*3+i];
+ piTriList_out[t0*3+i] = piTriList_out[t1*3+i];
+ piTriList_out[t1*3+i] = index;
+ }
+ {
+ const STriInfo tri_info = pTriInfos[t0];
+ pTriInfos[t0] = pTriInfos[t1];
+ pTriInfos[t1] = tri_info;
+ }
+ }
+ else
+ bStillFindingGoodOnes = TFALSE; // this is not supposed to happen
+ }
+
+ if (bStillFindingGoodOnes) ++t;
+ }
+
+ assert(bStillFindingGoodOnes); // code will still work.
+ assert(iNrTrianglesIn == t);
+}
+
+static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris)
+{
+ int t=0, i=0;
+ // deal with degenerate triangles
+ // punishment for degenerate triangles is O(N^2)
+ for (t=iNrTrianglesIn; t<iTotTris; t++)
+ {
+ // degenerate triangles on a quad with one good triangle are skipped
+ // here but processed in the next loop
+ const tbool bSkip = (pTriInfos[t].iFlag&QUAD_ONE_DEGEN_TRI)!=0 ? TTRUE : TFALSE;
+
+ if (!bSkip)
+ {
+ for (i=0; i<3; i++)
+ {
+ const int index1 = piTriListIn[t*3+i];
+ // search through the good triangles
+ tbool bNotFound = TTRUE;
+ int j=0;
+ while (bNotFound && j<(3*iNrTrianglesIn))
+ {
+ const int index2 = piTriListIn[j];
+ if (index1==index2) bNotFound=TFALSE;
+ else ++j;
+ }
+
+ if (!bNotFound)
+ {
+ const int iTri = j/3;
+ const int iVert = j%3;
+ const int iSrcVert=pTriInfos[iTri].vert_num[iVert];
+ const int iSrcOffs=pTriInfos[iTri].iTSpacesOffs;
+ const int iDstVert=pTriInfos[t].vert_num[i];
+ const int iDstOffs=pTriInfos[t].iTSpacesOffs;
+
+ // copy tspace
+ psTspace[iDstOffs+iDstVert] = psTspace[iSrcOffs+iSrcVert];
+ }
+ }
+ }
+ }
+
+ // deal with degenerate quads with one good triangle
+ for (t=0; t<iNrTrianglesIn; t++)
+ {
+ // this triangle belongs to a quad where the
+ // other triangle is degenerate
+ if ( (pTriInfos[t].iFlag&QUAD_ONE_DEGEN_TRI)!=0 )
+ {
+ SVec3 vDstP;
+ int iOrgF=-1, i=0;
+ tbool bNotFound;
+ unsigned char * pV = pTriInfos[t].vert_num;
+ int iFlag = (1<<pV[0]) | (1<<pV[1]) | (1<<pV[2]);
+ int iMissingIndex = 0;
+ if ((iFlag&2)==0) iMissingIndex=1;
+ else if ((iFlag&4)==0) iMissingIndex=2;
+ else if ((iFlag&8)==0) iMissingIndex=3;
+
+ iOrgF = pTriInfos[t].iOrgFaceNumber;
+ vDstP = GetPosition(pContext, MakeIndex(iOrgF, iMissingIndex));
+ bNotFound = TTRUE;
+ i=0;
+ while (bNotFound && i<3)
+ {
+ const int iVert = pV[i];
+ const SVec3 vSrcP = GetPosition(pContext, MakeIndex(iOrgF, iVert));
+ if (veq(vSrcP, vDstP)==TTRUE)
+ {
+ const int iOffs = pTriInfos[t].iTSpacesOffs;
+ psTspace[iOffs+iMissingIndex] = psTspace[iOffs+iVert];
+ bNotFound=TFALSE;
+ }
+ else
+ ++i;
+ }
+ assert(!bNotFound);
+ }
+ }
+}
diff --git a/scene/resources/mikktspace.h b/scene/resources/mikktspace.h
new file mode 100644
index 0000000000..52c44a713c
--- /dev/null
+++ b/scene/resources/mikktspace.h
@@ -0,0 +1,145 @@
+/** \file mikktspace/mikktspace.h
+ * \ingroup mikktspace
+ */
+/**
+ * Copyright (C) 2011 by Morten S. Mikkelsen
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef __MIKKTSPACE_H__
+#define __MIKKTSPACE_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Author: Morten S. Mikkelsen
+ * Version: 1.0
+ *
+ * The files mikktspace.h and mikktspace.c are designed to be
+ * stand-alone files and it is important that they are kept this way.
+ * Not having dependencies on structures/classes/libraries specific
+ * to the program, in which they are used, allows them to be copied
+ * and used as is into any tool, program or plugin.
+ * The code is designed to consistently generate the same
+ * tangent spaces, for a given mesh, in any tool in which it is used.
+ * This is done by performing an internal welding step and subsequently an order-independent evaluation
+ * of tangent space for meshes consisting of triangles and quads.
+ * This means faces can be received in any order and the same is true for
+ * the order of vertices of each face. The generated result will not be affected
+ * by such reordering. Additionally, whether degenerate (vertices or texture coordinates)
+ * primitives are present or not will not affect the generated results either.
+ * Once tangent space calculation is done the vertices of degenerate primitives will simply
+ * inherit tangent space from neighboring non degenerate primitives.
+ * The analysis behind this implementation can be found in my master's thesis
+ * which is available for download --> http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf
+ * Note that though the tangent spaces at the vertices are generated in an order-independent way,
+ * by this implementation, the interpolated tangent space is still affected by which diagonal is
+ * chosen to split each quad. A sensible solution is to have your tools pipeline always
+ * split quads by the shortest diagonal. This choice is order-independent and works with mirroring.
+ * If these have the same length then compare the diagonals defined by the texture coordinates.
+ * XNormal which is a tool for baking normal maps allows you to write your own tangent space plugin
+ * and also quad triangulator plugin.
+ */
+
+
+typedef int tbool;
+typedef struct SMikkTSpaceContext SMikkTSpaceContext;
+
+typedef struct {
+ // Returns the number of faces (triangles/quads) on the mesh to be processed.
+ int (*m_getNumFaces)(const SMikkTSpaceContext * pContext);
+
+ // Returns the number of vertices on face number iFace
+ // iFace is a number in the range {0, 1, ..., getNumFaces()-1}
+ int (*m_getNumVerticesOfFace)(const SMikkTSpaceContext * pContext, const int iFace);
+
+ // returns the position/normal/texcoord of the referenced face of vertex number iVert.
+ // iVert is in the range {0,1,2} for triangles and {0,1,2,3} for quads.
+ void (*m_getPosition)(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert);
+ void (*m_getNormal)(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert);
+ void (*m_getTexCoord)(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert);
+
+ // either (or both) of the two setTSpace callbacks can be set.
+ // The call-back m_setTSpaceBasic() is sufficient for basic normal mapping.
+
+ // This function is used to return the tangent and fSign to the application.
+ // fvTangent is a unit length vector.
+ // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level.
+ // bitangent = fSign * cross(vN, tangent);
+ // Note that the results are returned unindexed. It is possible to generate a new index list
+ // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results.
+ // DO NOT! use an already existing index list.
+ void (*m_setTSpaceBasic)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert);
+
+ // This function is used to return tangent space results to the application.
+ // fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are their
+ // true magnitudes which can be used for relief mapping effects.
+ // fvBiTangent is the "real" bitangent and thus may not be perpendicular to fvTangent.
+ // However, both are perpendicular to the vertex normal.
+ // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level.
+ // fSign = bIsOrientationPreserving ? 1.0f : (-1.0f);
+ // bitangent = fSign * cross(vN, tangent);
+ // Note that the results are returned unindexed. It is possible to generate a new index list
+ // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results.
+ // DO NOT! use an already existing index list.
+ void (*m_setTSpace)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
+ const tbool bIsOrientationPreserving, const int iFace, const int iVert);
+} SMikkTSpaceInterface;
+
+struct SMikkTSpaceContext
+{
+ SMikkTSpaceInterface * m_pInterface; // initialized with callback functions
+ void * m_pUserData; // pointer to client side mesh data etc. (passed as the first parameter with every interface call)
+};
+
+// these are both thread safe!
+tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext); // Default (recommended) fAngularThreshold is 180 degrees (which means threshold disabled)
+tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThreshold);
+
+
+// To avoid visual errors (distortions/unwanted hard edges in lighting), when using sampled normal maps, the
+// normal map sampler must use the exact inverse of the pixel shader transformation.
+// The most efficient transformation we can possibly do in the pixel shader is
+// achieved by using, directly, the "unnormalized" interpolated tangent, bitangent and vertex normal: vT, vB and vN.
+// pixel shader (fast transform out)
+// vNout = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
+// where vNt is the tangent space normal. The normal map sampler must likewise use the
+// interpolated and "unnormalized" tangent, bitangent and vertex normal to be compliant with the pixel shader.
+// sampler does (exact inverse of pixel shader):
+// float3 row0 = cross(vB, vN);
+// float3 row1 = cross(vN, vT);
+// float3 row2 = cross(vT, vB);
+// float fSign = dot(vT, row0)<0 ? -1 : 1;
+// vNt = normalize( fSign * float3(dot(vNout,row0), dot(vNout,row1), dot(vNout,row2)) );
+// where vNout is the sampled normal in some chosen 3D space.
+//
+// Should you choose to reconstruct the bitangent in the pixel shader instead
+// of the vertex shader, as explained earlier, then be sure to do this in the normal map sampler also.
+// Finally, beware of quad triangulations. If the normal map sampler doesn't use the same triangulation of
+// quads as your renderer then problems will occur since the interpolated tangent spaces will differ
+// eventhough the vertex level tangent spaces match. This can be solved either by triangulating before
+// sampling/exporting or by using the order-independent choice of diagonal for splitting quads suggested earlier.
+// However, this must be used both by the sampler and your tools/rendering pipeline.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 3bd7314778..5883686f20 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -29,6 +29,9 @@
#include "packed_scene.h"
#include "globals.h"
#include "io/resource_loader.h"
+#include "scene/3d/spatial.h"
+#include "scene/gui/control.h"
+#include "scene/2d/node_2d.h"
bool PackedScene::can_instance() const {
@@ -80,9 +83,28 @@ Node *PackedScene::instance(bool p_gen_edit_state) const {
} else {
//create anew
Object * obj = ObjectTypeDB::instance(snames[ n.type ]);
- ERR_FAIL_COND_V(!obj,NULL);
+ if (!obj || !obj->cast_to<Node>()) {
+ if (obj) {
+ memdelete(obj);
+ obj=NULL;
+ }
+ WARN_PRINT(String("Warning node of type "+snames[n.type].operator String()+" does not exist.").ascii().get_data());
+ if (n.parent>=0 && n.parent<nc && ret_nodes[n.parent]) {
+ if (ret_nodes[n.parent]->cast_to<Spatial>()) {
+ obj = memnew( Spatial );
+ } else if (ret_nodes[n.parent]->cast_to<Control>()) {
+ obj = memnew( Control );
+ } else if (ret_nodes[n.parent]->cast_to<Node2D>()) {
+ obj = memnew( Node2D );
+ }
+
+ }
+ if (!obj) {
+ obj = memnew( Node );
+ }
+ }
+
node = obj->cast_to<Node>();
- ERR_FAIL_COND_V(!node,NULL);
}
@@ -225,22 +247,38 @@ Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<
p_node->get_property_list(&plist);
for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
+
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
continue;
+ }
String name = E->get().name;
Variant value = p_node->get( E->get().name );
- if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())
+ if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) {
continue;
+ }
if (nd.instance>=0) {
//only save changed properties in instance
- if (!instance_state.has(name))
+ /*
+ // this was commented because it would not save properties created from within script
+ // done with _get_property_list, that are not in the original node.
+ // if some property is not saved, check again
+
+ if (!instance_state.has(name)) {
+ print_line("skip not in instance");
+ continue;
+ }*/
+
+ if (E->get().usage & PROPERTY_USAGE_NO_INSTANCE_STATE) {
continue;
- if (instance_state[name]==value)
+ }
+
+ if (instance_state[name]==value) {
continue;
+ }
}
diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp
index afb0ae1815..9f691d6ad3 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;
}
}
@@ -529,7 +531,7 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const {
float d = p_point.distance_squared_to(points[i].pos);
if (d<closest_dist) {
- d=closest_dist;
+ closest_dist=d;
closest_idx=i;
}
diff --git a/scene/resources/scene_preloader.cpp b/scene/resources/scene_preloader.cpp
index 59d8cae970..e37a2c4967 100644
--- a/scene/resources/scene_preloader.cpp
+++ b/scene/resources/scene_preloader.cpp
@@ -26,430 +26,429 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "scene_preloader.h"
-#include "scene/io/scene_loader.h"
-#include "globals.h"
-
-bool ScenePreloader::can_instance() const {
-
- return nodes.size()>0;
-}
-
-Node *ScenePreloader::instance() const {
-
- int nc = nodes.size();
- ERR_FAIL_COND_V(nc==0,NULL);
-
- const StringName*snames=NULL;
- int sname_count=names.size();
- if (sname_count)
- snames=&names[0];
-
- const Variant*props=NULL;
- int prop_count=variants.size();
- if (prop_count)
- props=&variants[0];
-
- Vector<Variant> properties;
-
- const NodeData *nd = &nodes[0];
-
- Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc );
-
- for(int i=0;i<nc;i++) {
-
- const NodeData &n=nd[i];
-
-
- if (!ObjectTypeDB::is_type_enabled(snames[n.type])) {
- ret_nodes[i]=NULL;
- continue;
- }
-
- Object * obj = ObjectTypeDB::instance(snames[ n.type ]);
- ERR_FAIL_COND_V(!obj,NULL);
- Node *node = obj->cast_to<Node>();
- ERR_FAIL_COND_V(!node,NULL);
-
- int nprop_count=n.properties.size();
- if (nprop_count) {
-
- const NodeData::Property* nprops=&n.properties[0];
-
- for(int j=0;j<nprop_count;j++) {
-
- bool valid;
- node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid);
- }
-
-
- }
-
- node->set_name( snames[ n.name ] );
- ret_nodes[i]=node;
- if (i>0) {
- ERR_FAIL_INDEX_V(n.parent,i,NULL);
- ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL);
- ret_nodes[n.parent]->add_child(node);
- }
- }
-
-
- //do connections
-
- int cc = connections.size();
- const ConnectionData *cdata = connections.ptr();
-
- for(int i=0;i<cc;i++) {
-
- const ConnectionData &c=cdata[i];
- ERR_FAIL_INDEX_V( c.from, nc, NULL );
- ERR_FAIL_INDEX_V( c.to, nc, NULL );
-
- Vector<Variant> binds;
- if (c.binds.size()) {
- binds.resize(c.binds.size());
- for(int j=0;j<c.binds.size();j++)
- binds[j]=props[ c.binds[j] ];
- }
-
- if (!ret_nodes[c.from] || !ret_nodes[c.to])
- continue;
- ret_nodes[c.from]->connect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST );
- }
-
- return ret_nodes[0];
-
-}
-
-
-static int _nm_get_string(const String& p_string, Map<StringName,int> &name_map) {
-
- if (name_map.has(p_string))
- return name_map[p_string];
-
- int idx = name_map.size();
- name_map[p_string]=idx;
- return idx;
-}
-
-static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher> &variant_map) {
-
- if (variant_map.has(p_variant))
- return variant_map[p_variant];
-
- int idx = variant_map.size();
- variant_map[p_variant]=idx;
- return idx;
-}
-
-void ScenePreloader::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) {
-
- if (p_node!=p_owner && !p_node->get_owner())
- return;
-
- NodeData nd;
- nd.name=_nm_get_string(p_node->get_name(),name_map);
- nd.type=_nm_get_string(p_node->get_type(),name_map);
- nd.parent=p_parent_idx;
-
- List<PropertyInfo> plist;
- p_node->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
-
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
- continue;
-
- NodeData::Property prop;
- prop.name=_nm_get_string(E->get().name,name_map);
- prop.value=_vm_get_variant( p_node->get( E->get().name ), variant_map);
- nd.properties.push_back(prop);
- }
-
- int idx = nodes.size();
- node_map[p_node]=idx;
- nodes.push_back(nd);
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- Node *c=p_node->get_child(i);
- _parse_node(p_owner,c,idx,name_map,variant_map,node_map);
- }
-
-
-
-}
-
-void ScenePreloader::_parse_connections(Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,bool p_instance) {
-
-
- List<MethodInfo> signals;
- p_node->get_signal_list(&signals);
-
- for(List<MethodInfo>::Element *E=signals.front();E;E=E->next()) {
-
- List<Node::Connection> conns;
- p_node->get_signal_connection_list(E->get().name,&conns);
- for(List<Node::Connection>::Element *F=conns.front();F;F=F->next()) {
-
- const Node::Connection &c = F->get();
- if (!(c.flags&CONNECT_PERSIST))
- continue;
- Node *n=c.target->cast_to<Node>();
- if (!n)
- continue;
-
- if (!node_map.has(n))
- continue;
-
- ConnectionData cd;
- cd.from=node_map[p_node];
- cd.to=node_map[n];
- cd.method=_nm_get_string(c.method,name_map);
- cd.signal=_nm_get_string(c.signal,name_map);
- for(int i=0;i<c.binds.size();i++) {
-
- cd.binds.push_back( _vm_get_variant(c.binds[i],variant_map));
- }
- connections.push_back(cd);
- }
- }
-
-}
-
-
-Error ScenePreloader::load_scene(const String& p_path) {
-
- return ERR_CANT_OPEN;
-#if 0
- if (path==p_path)
- return OK;
-
- String p=Globals::get_singleton()->localize_path(p_path);
- clear();
-
- Node *scene = SceneLoader::load(p);
-
- ERR_FAIL_COND_V(!scene,ERR_CANT_OPEN);
-
- path=p;
-
- Map<StringName,int> name_map;
- HashMap<Variant,int,VariantHasher> variant_map;
- Map<Node*,int> node_map;
-
- _parse_node(scene,scene,-1,name_map,variant_map,node_map);
-
-
- names.resize(name_map.size());
-
- for(Map<StringName,int>::Element *E=name_map.front();E;E=E->next()) {
-
- names[E->get()]=E->key();
- }
-
- variants.resize(variant_map.size());
- const Variant *K=NULL;
- while((K=variant_map.next(K))) {
-
- int idx = variant_map[*K];
- variants[idx]=*K;
- }
-
-
- memdelete(scene); // <- me falto esto :(
- return OK;
-#endif
-}
-
-String ScenePreloader::get_scene_path() const {
-
- return path;
-}
-
-void ScenePreloader::clear() {
-
- names.clear();
- variants.clear();
- nodes.clear();
- connections.clear();
-
-}
-
-void ScenePreloader::_set_bundled_scene(const Dictionary& d) {
-
-
- ERR_FAIL_COND( !d.has("names"));
- ERR_FAIL_COND( !d.has("variants"));
- ERR_FAIL_COND( !d.has("node_count"));
- ERR_FAIL_COND( !d.has("nodes"));
- ERR_FAIL_COND( !d.has("conn_count"));
- ERR_FAIL_COND( !d.has("conns"));
- ERR_FAIL_COND( !d.has("path"));
-
- DVector<String> snames = d["names"];
- if (snames.size()) {
-
- int namecount = snames.size();
- names.resize(namecount);
- DVector<String>::Read r =snames.read();
- for(int i=0;i<names.size();i++)
- names[i]=r[i];
- }
-
- Array svariants = d["variants"];
-
- if (svariants.size()) {
- int varcount=svariants.size();
- variants.resize(varcount);
- for(int i=0;i<varcount;i++) {
-
- variants[i]=svariants[i];
- }
-
- } else {
- variants.clear();
- }
-
- nodes.resize(d["node_count"]);
- int nc=nodes.size();
- if (nc) {
- DVector<int> snodes = d["nodes"];
- DVector<int>::Read r = snodes.read();
- int idx=0;
- for(int i=0;i<nc;i++) {
- NodeData &nd = nodes[i];
- nd.parent=r[idx++];
- nd.type=r[idx++];
- nd.name=r[idx++];
- nd.properties.resize(r[idx++]);
- for(int j=0;j<nd.properties.size();j++) {
-
- nd.properties[j].name=r[idx++];
- nd.properties[j].value=r[idx++];
- }
- }
-
- }
-
- connections.resize(d["conn_count"]);
- int cc=connections.size();
-
- if (cc) {
-
- DVector<int> sconns = d["conns"];
- DVector<int>::Read r = sconns.read();
- int idx=0;
- for(int i=0;i<nc;i++) {
- ConnectionData &cd = connections[nc];
- cd.from=r[idx++];
- cd.to=r[idx++];
- cd.signal=r[idx++];
- cd.method=r[idx++];
- cd.binds.resize(r[idx++]);
- for(int j=0;j<cd.binds.size();j++) {
-
- cd.binds[j]=r[idx++];
- }
- }
-
- }
-
-
-
- path=d["path"];
-
-}
-
-Dictionary ScenePreloader::_get_bundled_scene() const {
-
- DVector<String> rnames;
- rnames.resize(names.size());
-
- if (names.size()) {
-
- DVector<String>::Write r=rnames.write();
-
- for(int i=0;i<names.size();i++)
- r[i]=names[i];
- }
-
- Dictionary d;
- d["names"]=rnames;
- d["variants"]=variants;
-
- Vector<int> rnodes;
- d["node_count"]=nodes.size();
-
- for(int i=0;i<nodes.size();i++) {
-
- const NodeData &nd=nodes[i];
- rnodes.push_back(nd.parent);
- rnodes.push_back(nd.type);
- rnodes.push_back(nd.name);
- rnodes.push_back(nd.properties.size());
- for(int j=0;j<nd.properties.size();j++) {
-
- rnodes.push_back(nd.properties[j].name);
- rnodes.push_back(nd.properties[j].value);
- }
- }
-
- d["nodes"]=rnodes;
-
- Vector<int> rconns;
- d["conn_count"]=connections.size();
-
- for(int i=0;i<connections.size();i++) {
-
- const ConnectionData &cd=connections[i];
- rconns.push_back(cd.from);
- rconns.push_back(cd.to);
- rconns.push_back(cd.signal);
- rconns.push_back(cd.method);
- rconns.push_back(cd.binds.size());
- for(int j=0;j<cd.binds.size();i++)
- rconns.push_back(cd.binds[j]);
-
- }
-
- d["conns"]=rconns;
-
- d["path"]=path;
-
- return d;
-
-
-}
-
-void ScenePreloader::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("load_scene","path"),&ScenePreloader::load_scene);
- ObjectTypeDB::bind_method(_MD("get_scene_path"),&ScenePreloader::get_scene_path);
- ObjectTypeDB::bind_method(_MD("instance:Node"),&ScenePreloader::instance);
- ObjectTypeDB::bind_method(_MD("can_instance"),&ScenePreloader::can_instance);
- ObjectTypeDB::bind_method(_MD("_set_bundled_scene"),&ScenePreloader::_set_bundled_scene);
- ObjectTypeDB::bind_method(_MD("_get_bundled_scene"),&ScenePreloader::_get_bundled_scene);
-
- ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_BUNDLE),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene"));
-#if 0
- List<String> extensions;
- SceneLoader::get_recognized_extensions(&extensions);
- String exthint;
- for (List<String>::Element*E=extensions.front();E;E=E->next()) {
-
- if (exthint!="")
- exthint+=",";
- exthint+="*."+E->get();
- }
-
- exthint+="; Scenes";
-
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"scene",PROPERTY_HINT_FILE,exthint),_SCS("load_scene"),_SCS("get_scene_path"));
-#endif
-}
-
-ScenePreloader::ScenePreloader() {
-
-
-}
+#include "scene_preloader.h"
+#include "globals.h"
+
+bool ScenePreloader::can_instance() const {
+
+ return nodes.size()>0;
+}
+
+Node *ScenePreloader::instance() const {
+
+ int nc = nodes.size();
+ ERR_FAIL_COND_V(nc==0,NULL);
+
+ const StringName*snames=NULL;
+ int sname_count=names.size();
+ if (sname_count)
+ snames=&names[0];
+
+ const Variant*props=NULL;
+ int prop_count=variants.size();
+ if (prop_count)
+ props=&variants[0];
+
+ Vector<Variant> properties;
+
+ const NodeData *nd = &nodes[0];
+
+ Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc );
+
+ for(int i=0;i<nc;i++) {
+
+ const NodeData &n=nd[i];
+
+
+ if (!ObjectTypeDB::is_type_enabled(snames[n.type])) {
+ ret_nodes[i]=NULL;
+ continue;
+ }
+
+ Object * obj = ObjectTypeDB::instance(snames[ n.type ]);
+ ERR_FAIL_COND_V(!obj,NULL);
+ Node *node = obj->cast_to<Node>();
+ ERR_FAIL_COND_V(!node,NULL);
+
+ int nprop_count=n.properties.size();
+ if (nprop_count) {
+
+ const NodeData::Property* nprops=&n.properties[0];
+
+ for(int j=0;j<nprop_count;j++) {
+
+ bool valid;
+ node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid);
+ }
+
+
+ }
+
+ node->set_name( snames[ n.name ] );
+ ret_nodes[i]=node;
+ if (i>0) {
+ ERR_FAIL_INDEX_V(n.parent,i,NULL);
+ ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL);
+ ret_nodes[n.parent]->add_child(node);
+ }
+ }
+
+
+ //do connections
+
+ int cc = connections.size();
+ const ConnectionData *cdata = connections.ptr();
+
+ for(int i=0;i<cc;i++) {
+
+ const ConnectionData &c=cdata[i];
+ ERR_FAIL_INDEX_V( c.from, nc, NULL );
+ ERR_FAIL_INDEX_V( c.to, nc, NULL );
+
+ Vector<Variant> binds;
+ if (c.binds.size()) {
+ binds.resize(c.binds.size());
+ for(int j=0;j<c.binds.size();j++)
+ binds[j]=props[ c.binds[j] ];
+ }
+
+ if (!ret_nodes[c.from] || !ret_nodes[c.to])
+ continue;
+ ret_nodes[c.from]->connect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST );
+ }
+
+ return ret_nodes[0];
+
+}
+
+
+static int _nm_get_string(const String& p_string, Map<StringName,int> &name_map) {
+
+ if (name_map.has(p_string))
+ return name_map[p_string];
+
+ int idx = name_map.size();
+ name_map[p_string]=idx;
+ return idx;
+}
+
+static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher> &variant_map) {
+
+ if (variant_map.has(p_variant))
+ return variant_map[p_variant];
+
+ int idx = variant_map.size();
+ variant_map[p_variant]=idx;
+ return idx;
+}
+
+void ScenePreloader::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) {
+
+ if (p_node!=p_owner && !p_node->get_owner())
+ return;
+
+ NodeData nd;
+ nd.name=_nm_get_string(p_node->get_name(),name_map);
+ nd.type=_nm_get_string(p_node->get_type(),name_map);
+ nd.parent=p_parent_idx;
+
+ List<PropertyInfo> plist;
+ p_node->get_property_list(&plist);
+ for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
+
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
+ continue;
+
+ NodeData::Property prop;
+ prop.name=_nm_get_string(E->get().name,name_map);
+ prop.value=_vm_get_variant( p_node->get( E->get().name ), variant_map);
+ nd.properties.push_back(prop);
+ }
+
+ int idx = nodes.size();
+ node_map[p_node]=idx;
+ nodes.push_back(nd);
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ Node *c=p_node->get_child(i);
+ _parse_node(p_owner,c,idx,name_map,variant_map,node_map);
+ }
+
+
+
+}
+
+void ScenePreloader::_parse_connections(Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,bool p_instance) {
+
+
+ List<MethodInfo> signals;
+ p_node->get_signal_list(&signals);
+
+ for(List<MethodInfo>::Element *E=signals.front();E;E=E->next()) {
+
+ List<Node::Connection> conns;
+ p_node->get_signal_connection_list(E->get().name,&conns);
+ for(List<Node::Connection>::Element *F=conns.front();F;F=F->next()) {
+
+ const Node::Connection &c = F->get();
+ if (!(c.flags&CONNECT_PERSIST))
+ continue;
+ Node *n=c.target->cast_to<Node>();
+ if (!n)
+ continue;
+
+ if (!node_map.has(n))
+ continue;
+
+ ConnectionData cd;
+ cd.from=node_map[p_node];
+ cd.to=node_map[n];
+ cd.method=_nm_get_string(c.method,name_map);
+ cd.signal=_nm_get_string(c.signal,name_map);
+ for(int i=0;i<c.binds.size();i++) {
+
+ cd.binds.push_back( _vm_get_variant(c.binds[i],variant_map));
+ }
+ connections.push_back(cd);
+ }
+ }
+
+}
+
+
+Error ScenePreloader::load_scene(const String& p_path) {
+
+ return ERR_CANT_OPEN;
+#if 0
+ if (path==p_path)
+ return OK;
+
+ String p=Globals::get_singleton()->localize_path(p_path);
+ clear();
+
+ Node *scene = SceneLoader::load(p);
+
+ ERR_FAIL_COND_V(!scene,ERR_CANT_OPEN);
+
+ path=p;
+
+ Map<StringName,int> name_map;
+ HashMap<Variant,int,VariantHasher> variant_map;
+ Map<Node*,int> node_map;
+
+ _parse_node(scene,scene,-1,name_map,variant_map,node_map);
+
+
+ names.resize(name_map.size());
+
+ for(Map<StringName,int>::Element *E=name_map.front();E;E=E->next()) {
+
+ names[E->get()]=E->key();
+ }
+
+ variants.resize(variant_map.size());
+ const Variant *K=NULL;
+ while((K=variant_map.next(K))) {
+
+ int idx = variant_map[*K];
+ variants[idx]=*K;
+ }
+
+
+ memdelete(scene); // <- me falto esto :(
+ return OK;
+#endif
+}
+
+String ScenePreloader::get_scene_path() const {
+
+ return path;
+}
+
+void ScenePreloader::clear() {
+
+ names.clear();
+ variants.clear();
+ nodes.clear();
+ connections.clear();
+
+}
+
+void ScenePreloader::_set_bundled_scene(const Dictionary& d) {
+
+
+ ERR_FAIL_COND( !d.has("names"));
+ ERR_FAIL_COND( !d.has("variants"));
+ ERR_FAIL_COND( !d.has("node_count"));
+ ERR_FAIL_COND( !d.has("nodes"));
+ ERR_FAIL_COND( !d.has("conn_count"));
+ ERR_FAIL_COND( !d.has("conns"));
+ ERR_FAIL_COND( !d.has("path"));
+
+ DVector<String> snames = d["names"];
+ if (snames.size()) {
+
+ int namecount = snames.size();
+ names.resize(namecount);
+ DVector<String>::Read r =snames.read();
+ for(int i=0;i<names.size();i++)
+ names[i]=r[i];
+ }
+
+ Array svariants = d["variants"];
+
+ if (svariants.size()) {
+ int varcount=svariants.size();
+ variants.resize(varcount);
+ for(int i=0;i<varcount;i++) {
+
+ variants[i]=svariants[i];
+ }
+
+ } else {
+ variants.clear();
+ }
+
+ nodes.resize(d["node_count"]);
+ int nc=nodes.size();
+ if (nc) {
+ DVector<int> snodes = d["nodes"];
+ DVector<int>::Read r = snodes.read();
+ int idx=0;
+ for(int i=0;i<nc;i++) {
+ NodeData &nd = nodes[i];
+ nd.parent=r[idx++];
+ nd.type=r[idx++];
+ nd.name=r[idx++];
+ nd.properties.resize(r[idx++]);
+ for(int j=0;j<nd.properties.size();j++) {
+
+ nd.properties[j].name=r[idx++];
+ nd.properties[j].value=r[idx++];
+ }
+ }
+
+ }
+
+ connections.resize(d["conn_count"]);
+ int cc=connections.size();
+
+ if (cc) {
+
+ DVector<int> sconns = d["conns"];
+ DVector<int>::Read r = sconns.read();
+ int idx=0;
+ for(int i=0;i<nc;i++) {
+ ConnectionData &cd = connections[nc];
+ cd.from=r[idx++];
+ cd.to=r[idx++];
+ cd.signal=r[idx++];
+ cd.method=r[idx++];
+ cd.binds.resize(r[idx++]);
+ for(int j=0;j<cd.binds.size();j++) {
+
+ cd.binds[j]=r[idx++];
+ }
+ }
+
+ }
+
+
+
+ path=d["path"];
+
+}
+
+Dictionary ScenePreloader::_get_bundled_scene() const {
+
+ DVector<String> rnames;
+ rnames.resize(names.size());
+
+ if (names.size()) {
+
+ DVector<String>::Write r=rnames.write();
+
+ for(int i=0;i<names.size();i++)
+ r[i]=names[i];
+ }
+
+ Dictionary d;
+ d["names"]=rnames;
+ d["variants"]=variants;
+
+ Vector<int> rnodes;
+ d["node_count"]=nodes.size();
+
+ for(int i=0;i<nodes.size();i++) {
+
+ const NodeData &nd=nodes[i];
+ rnodes.push_back(nd.parent);
+ rnodes.push_back(nd.type);
+ rnodes.push_back(nd.name);
+ rnodes.push_back(nd.properties.size());
+ for(int j=0;j<nd.properties.size();j++) {
+
+ rnodes.push_back(nd.properties[j].name);
+ rnodes.push_back(nd.properties[j].value);
+ }
+ }
+
+ d["nodes"]=rnodes;
+
+ Vector<int> rconns;
+ d["conn_count"]=connections.size();
+
+ for(int i=0;i<connections.size();i++) {
+
+ const ConnectionData &cd=connections[i];
+ rconns.push_back(cd.from);
+ rconns.push_back(cd.to);
+ rconns.push_back(cd.signal);
+ rconns.push_back(cd.method);
+ rconns.push_back(cd.binds.size());
+ for(int j=0;j<cd.binds.size();i++)
+ rconns.push_back(cd.binds[j]);
+
+ }
+
+ d["conns"]=rconns;
+
+ d["path"]=path;
+
+ return d;
+
+
+}
+
+void ScenePreloader::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("load_scene","path"),&ScenePreloader::load_scene);
+ ObjectTypeDB::bind_method(_MD("get_scene_path"),&ScenePreloader::get_scene_path);
+ ObjectTypeDB::bind_method(_MD("instance:Node"),&ScenePreloader::instance);
+ ObjectTypeDB::bind_method(_MD("can_instance"),&ScenePreloader::can_instance);
+ ObjectTypeDB::bind_method(_MD("_set_bundled_scene"),&ScenePreloader::_set_bundled_scene);
+ ObjectTypeDB::bind_method(_MD("_get_bundled_scene"),&ScenePreloader::_get_bundled_scene);
+
+ ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_BUNDLE),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene"));
+#if 0
+ List<String> extensions;
+ SceneLoader::get_recognized_extensions(&extensions);
+ String exthint;
+ for (List<String>::Element*E=extensions.front();E;E=E->next()) {
+
+ if (exthint!="")
+ exthint+=",";
+ exthint+="*."+E->get();
+ }
+
+ exthint+="; Scenes";
+
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"scene",PROPERTY_HINT_FILE,exthint),_SCS("load_scene"),_SCS("get_scene_path"));
+#endif
+}
+
+ScenePreloader::ScenePreloader() {
+
+
+}
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..9703799a48 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -27,129 +27,351 @@
/* 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 {
+
+ List<Connection> connections;
+ get_node_connections(p_type,&connections);
+ Array arr(true);
+ for (List<Connection>::Element *E=connections.front();E;E=E->next()) {
+
+ 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);
-# if 0
-void ShaderGraph::_set(const String& p_name, const Variant& p_value) {
+ }
+ return arr;
+}
- if (p_name.begins_with("nodes/")) {
- int idx=p_name.get_slice("/",1).to_int();
- Dictionary data=p_value;
+void ShaderGraph::_set_data(const Dictionary &p_data) {
- ERR_FAIL_COND(!data.has("type"));
- String type=data["type"];
+ Dictionary d=p_data;
+ ERR_FAIL_COND(!d.has("shaders"));
+ Array sh=d["shaders"];
+ ERR_FAIL_COND(sh.size()!=3);
- VS::NodeType node_type=VS::NODE_TYPE_MAX;
- for(int i=0;i<NODE_TYPE_MAX;i++) {
+ 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) {
- if (type==VisualServer::shader_node_get_type_info((VS::NodeType)i).name)
- node_type=(VS::NodeType)i;
- }
+ 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];
- ERR_FAIL_COND(node_type==VS::NODE_TYPE_MAX);
+ Array conns=data[i+5];
+ ERR_FAIL_COND((conns.size()%3)!=0);
- 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"]);
- }
+ 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("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_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_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 +434,158 @@ 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_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_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 +595,1463 @@ 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();
+
}
-Variant ShaderGraph::node_get_param(int p_id) const {
+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];
- return VisualServer::get_singleton()->shader_node_get_param(shader,p_id);
}
-void ShaderGraph::connect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) {
+void ShaderGraph::texture_node_set_filter_strength(ShaderType p_type,float p_id,float p_strength){
- VisualServer::get_singleton()->shader_connect(shader,p_src_id,p_src_slot,p_dst_id,p_dst_slot);
- version++;
+ 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::disconnect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) {
- VisualServer::get_singleton()->shader_disconnect(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();
+
}
+ShaderGraph::ScalarOp ShaderGraph::scalar_op_node_get_op(ShaderType p_type,float p_id) const{
-void ShaderGraph::get_connections(List<Connection> *p_connections) 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);
- 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();
+
+}
+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);
}
-void ShaderGraph::shader_get_default_output_nodes(ShaderGraphType p_type,List<PropertyInfo> *p_outputs) {
- 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::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","SCREEN_UV","",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},
+ //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++;
+ }
}
-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 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_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_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) {
+
+ 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;
- 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_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( 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: {}
+}
+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("");
-}
-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: {}
+
+
+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("");
-}
-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: {}
+
+ 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];
+ }
+
+ }
+
+
+
+ shader[i].error=GRAPH_OK;
+
+ }
+
+ 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: {}
+ 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::_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]+");\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_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_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..55d09b4c38 100644
--- a/scene/resources/shader_graph.h
+++ b/scene/resources/shader_graph.h
@@ -29,87 +29,54 @@
#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_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_OUTPUT, // output (shader type dependent)
+ NODE_COMMENT, // comment
NODE_TYPE_MAX
};
- enum ShaderType {
- SHADER_VERTEX,
- SHADER_FRAGMENT,
- SHADER_LIGHT
- };
-
-private:
struct Connection {
@@ -119,70 +86,292 @@ 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];
+ };
- Array _get_connections_helper() const;
+ static const NodeSlotInfo node_slot_info[];
+
+ bool _pending_update_shader;
+ void _update_shader();
+ void _request_update();
+
+ 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
+ };
- ShaderGraph();
+ 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
+ };
+
+ 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 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 +381,28 @@ 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 );
+ RES_BASE_EXTENSION("sgp");
+
+public:
+
+
+ MaterialShaderGraph() : ShaderGraph(MODE_MATERIAL) {
+
+ }
+};
-#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/surface_tool.cpp b/scene/resources/surface_tool.cpp
index 2856101674..113fd8209d 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -105,7 +105,7 @@ void SurfaceTool::add_vertex( const Vector3& p_vertex) {
vtx.weights=last_weights;
vtx.bones=last_bones;
vtx.tangent=last_tangent.normal;
- vtx.binormal=last_tangent.normal.cross(last_normal).normalized() * last_tangent.d;
+ vtx.binormal=last_normal.cross(last_tangent.normal).normalized() * last_tangent.d;
vertex_array.push_back(vtx);
first=false;
format|=Mesh::ARRAY_FORMAT_VERTEX;
@@ -299,7 +299,9 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) {
w[idx+0]=v.tangent.x;
w[idx+1]=v.tangent.y;
w[idx+2]=v.tangent.z;
- float d = v.binormal.dot(v.normal.cross(v.tangent));
+
+ //float d = v.tangent.dot(v.binormal,v.normal);
+ float d = v.binormal.dot( v.normal.cross(v.tangent));
w[idx+3]=d<0 ? -1 : 1;
}
@@ -565,6 +567,7 @@ void SurfaceTool::create_from(const Ref<Mesh>& p_existing, int p_surface) {
clear();
primitive=p_existing->surface_get_primitive_type(p_surface);
_create_list(p_existing,p_surface,&vertex_array,&index_array,format);
+ material=p_existing->surface_get_material(p_surface);
}
@@ -611,165 +614,96 @@ void SurfaceTool::append_from(const Ref<Mesh>& p_existing, int p_surface,const T
}
+//mikktspace callbacks
+int SurfaceTool::mikktGetNumFaces(const SMikkTSpaceContext * pContext) {
-void SurfaceTool::generate_tangents() {
-
- ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV));
- ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL));
-
-
- if (index_array.size()) {
-
- Vector<List<Vertex>::Element*> vtx;
- vtx.resize(vertex_array.size());
- int idx=0;
- for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) {
- vtx[idx++]=E;
- E->get().binormal=Vector3();
- E->get().tangent=Vector3();
- }
-
- for (List<int>::Element *E=index_array.front();E;) {
-
- int i[3];
- i[0]=E->get();
- E=E->next();
- ERR_FAIL_COND(!E);
- i[1]=E->get();
- E=E->next();
- ERR_FAIL_COND(!E);
- i[2]=E->get();
- E=E->next();
- ERR_FAIL_COND(!E);
-
-
- Vector3 v1 = vtx[ i[0] ]->get().vertex;
- Vector3 v2 = vtx[ i[1] ]->get().vertex;
- Vector3 v3 = vtx[ i[2] ]->get().vertex;
-
- Vector2 w1 = vtx[ i[0] ]->get().uv;
- Vector2 w2 = vtx[ i[1] ]->get().uv;
- Vector2 w3 = vtx[ i[2] ]->get().uv;
-
-
- float x1 = v2.x - v1.x;
- float x2 = v3.x - v1.x;
- float y1 = v2.y - v1.y;
- float y2 = v3.y - v1.y;
- float z1 = v2.z - v1.z;
- float z2 = v3.z - v1.z;
-
- float s1 = w2.x - w1.x;
- float s2 = w3.x - w1.x;
- float t1 = w2.y - w1.y;
- float t2 = w3.y - w1.y;
-
- float r = (s1 * t2 - s2 * t1);
-
- Vector3 binormal,tangent;
-
- if (r==0) {
- binormal=Vector3(0,0,0);
- tangent=Vector3(0,0,0);
- } else {
- tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
- (t2 * z1 - t1 * z2) * r);
- binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
- (s1 * z2 - s2 * z1) * r);
- }
-
- tangent.normalize();
- binormal.normalize();
- Vector3 normal=Plane( v1, v2, v3 ).normal;
-
- Vector3 tangentp = tangent - normal * normal.dot( tangent );
- Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal));
-
- tangentp.normalize();
- binormalp.normalize();
+ Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData);
+ return varr.size()/3;
+}
+int SurfaceTool::mikktGetNumVerticesOfFace(const SMikkTSpaceContext * pContext, const int iFace){
+ return 3; //always 3
+}
+void SurfaceTool::mikktGetPosition(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert){
- for (int j=0;j<3;j++) {
- vtx[ i[j] ]->get().binormal+=binormalp;
- vtx[ i[j] ]->get().tangent+=tangentp;
+ Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData);
+ Vector3 v = varr[iFace*3+iVert]->get().vertex;
+ fvPosOut[0]=v.x;
+ fvPosOut[1]=v.y;
+ fvPosOut[2]=v.z;
- }
- }
- for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) {
- E->get().binormal.normalize();
- E->get().tangent.normalize();
- }
+}
+void SurfaceTool::mikktGetNormal(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert){
- } else {
+ Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData);
+ Vector3 v = varr[iFace*3+iVert]->get().normal;
+ fvNormOut[0]=v.x;
+ fvNormOut[1]=v.y;
+ fvNormOut[2]=v.z;
- for (List<Vertex>::Element *E=vertex_array.front();E;) {
+}
+void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert){
- List< Vertex >::Element *v[3];
- v[0]=E;
- v[1]=v[0]->next();
- ERR_FAIL_COND(!v[1]);
- v[2]=v[1]->next();
- ERR_FAIL_COND(!v[2]);
- E=v[2]->next();
+ 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;
- Vector3 v1 = v[0]->get().vertex;
- Vector3 v2 = v[1]->get().vertex;
- Vector3 v3 = v[2]->get().vertex;
+}
+void SurfaceTool::mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert){
- Vector2 w1 = v[0]->get().uv;
- Vector2 w2 = v[1]->get().uv;
- Vector2 w3 = v[2]->get().uv;
+ Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData);
+ Vertex &vtx = varr[iFace*3+iVert]->get();
+ vtx.tangent = Vector3(fvTangent[0],fvTangent[1],fvTangent[2]);
+ vtx.binormal = vtx.normal.cross(vtx.tangent) * fSign;
+}
- float x1 = v2.x - v1.x;
- float x2 = v3.x - v1.x;
- float y1 = v2.y - v1.y;
- float y2 = v3.y - v1.y;
- float z1 = v2.z - v1.z;
- float z2 = v3.z - v1.z;
- float s1 = w2.x - w1.x;
- float s2 = w3.x - w1.x;
- float t1 = w2.y - w1.y;
- float t2 = w3.y - w1.y;
+void SurfaceTool::generate_tangents() {
- float r = (s1 * t2 - s2 * t1);
+ ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV));
+ ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL));
- Vector3 binormal,tangent;
+ bool indexed = index_array.size()>0;
+ if (indexed)
+ deindex();
- if (r==0) {
- binormal=Vector3(0,0,0);
- tangent=Vector3(0,0,0);
- } else {
- tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
- (t2 * z1 - t1 * z2) * r);
- binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
- (s1 * z2 - s2 * z1) * r);
- }
- tangent.normalize();
- binormal.normalize();
- Vector3 normal=Plane( v1, v2, v3 ).normal;
+ SMikkTSpaceInterface mkif;
+ mkif.m_getNormal=mikktGetNormal;
+ mkif.m_getNumFaces=mikktGetNumFaces;
+ mkif.m_getNumVerticesOfFace=mikktGetNumVerticesOfFace;
+ mkif.m_getPosition=mikktGetPosition;
+ mkif.m_getTexCoord=mikktGetTexCoord;
+ mkif.m_setTSpaceBasic=mikktSetTSpaceBasic;
+ mkif.m_setTSpace=NULL;
- Vector3 tangentp = tangent - normal * normal.dot( tangent );
- Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal));
+ SMikkTSpaceContext msc;
+ msc.m_pInterface=&mkif;
- tangentp.normalize();
- binormalp.normalize();
+ Vector<List<Vertex>::Element*> vtx;
+ vtx.resize(vertex_array.size());
+ int idx=0;
+ for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) {
+ vtx[idx++]=E;
+ E->get().binormal=Vector3();
+ E->get().tangent=Vector3();
+ }
+ msc.m_pUserData=&vtx;
+ bool res = genTangSpaceDefault(&msc);
- for (int j=0;j<3;j++) {
- v[j]->get().binormal=binormalp;
- v[j]->get().tangent=tangentp;
+ ERR_FAIL_COND(!res);
+ format|=Mesh::ARRAY_FORMAT_TANGENT;
- }
- }
- }
+ if (indexed)
+ index();
- format|=Mesh::ARRAY_FORMAT_TANGENT;
}
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index fe82d3a4ce..fc5940145b 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -30,7 +30,7 @@
#define SURFACE_TOOL_H
#include "scene/resources/mesh.h"
-
+#include "mikktspace.h"
class SurfaceTool : public Reference {
@@ -82,6 +82,14 @@ private:
void _create_list(const Ref<Mesh>& p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index,int &lformat);
+
+ //mikktspace callbacks
+ static int mikktGetNumFaces(const SMikkTSpaceContext * pContext);
+ static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext * pContext, const int iFace);
+ static void mikktGetPosition(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert);
+ static void mikktGetNormal(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert);
+ static void mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert);
+ static void mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert);
protected:
static void _bind_methods();
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 5b31ba1f1b..dae055890b 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -79,6 +79,8 @@ void Texture::_bind_methods() {
BIND_CONSTANT( FLAG_FILTER );
BIND_CONSTANT( FLAG_VIDEO_SURFACE );
BIND_CONSTANT( FLAGS_DEFAULT );
+ BIND_CONSTANT( FLAG_ANISOTROPIC_FILTER );
+ BIND_CONSTANT( FLAG_CONVERT_TO_LINEAR );
}
@@ -179,7 +181,7 @@ void ImageTexture::_get_property_list( List<PropertyInfo> *p_list) const {
- p_list->push_back( PropertyInfo( Variant::INT, "flags", PROPERTY_HINT_FLAGS,"Mipmaps,Repeat,Filter") );
+ p_list->push_back( PropertyInfo( Variant::INT, "flags", PROPERTY_HINT_FLAGS,"Mipmaps,Repeat,Filter,Anisotropic,sRGB") );
p_list->push_back( PropertyInfo( Variant::IMAGE, "image", img_hint,String::num(lossy_storage_quality)) );
p_list->push_back( PropertyInfo( Variant::VECTOR2, "size",PROPERTY_HINT_NONE, ""));
p_list->push_back( PropertyInfo( Variant::INT, "storage", PROPERTY_HINT_ENUM,"Uncompressed,Compress Lossy,Compress Lossless"));
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 86ff246498..4bb2f6d979 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -52,6 +52,8 @@ public:
FLAG_MIPMAPS=VisualServer::TEXTURE_FLAG_MIPMAPS,
FLAG_REPEAT=VisualServer::TEXTURE_FLAG_REPEAT,
FLAG_FILTER=VisualServer::TEXTURE_FLAG_FILTER,
+ FLAG_ANISOTROPIC_FILTER=VisualServer::TEXTURE_FLAG_ANISOTROPIC_FILTER,
+ FLAG_CONVERT_TO_LINEAR=VisualServer::TEXTURE_FLAG_CONVERT_TO_LINEAR,
FLAG_VIDEO_SURFACE=VisualServer::TEXTURE_FLAG_VIDEO_SURFACE,
FLAGS_DEFAULT=FLAG_MIPMAPS|FLAG_REPEAT|FLAG_FILTER,
};
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_2d.cpp b/scene/resources/world_2d.cpp
index aee7ddde00..0dd6a3d5e7 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -364,12 +364,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/scene_binds.cpp b/scene/scene_binds.cpp
deleted file mode 100644
index 5c6a02611f..0000000000
--- a/scene/scene_binds.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*************************************************************************/
-/* scene_binds.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 "scene_binds.h"
-
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-void SceneIO::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("load:Node","path"),&SceneIO::load);
- ObjectTypeDB::bind_method(_MD("save","path","scene:Node","flags","optimizer:OptimizedSaver","scene"),&SceneIO::save,DEFVAL(0),DEFVAL(Ref<OptimizedSaver>()));
- ObjectTypeDB::bind_method(_MD("load_interactive:SceneInteractiveLoader","path"),&SceneIO::load_interactive);
-}
-
-Node* SceneIO::load(const String& p_scene) {
-
- return SceneLoader::load(p_scene);
-}
-
-Error SceneIO::save(const String& p_path, Node *p_scene,int p_flags,const Ref<OptimizedSaver> &p_optimizer) {
-
- return SceneSaver::save(p_path,p_scene,p_flags,p_optimizer);
-}
-
-Ref<SceneInteractiveLoader> SceneIO::load_interactive(const String& p_scene) {
-
- return SceneLoader::load_interactive(p_scene);
-}
-
-#endif
diff --git a/scene/scene_binds.h b/scene/scene_binds.h
deleted file mode 100644
index 29e4b9ab60..0000000000
--- a/scene/scene_binds.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*************************************************************************/
-/* scene_binds.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 SCENE_BINDS_H
-#define SCENE_BINDS_H
-
-#include "scene/io/scene_loader.h"
-#include "scene/io/scene_saver.h"
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
-class SceneIO : public Object {
-
- OBJ_TYPE( SceneIO, Object );
-protected:
-
- static void _bind_methods();
-public:
-
- enum SaveFlags {
-
- SAVE_FLAG_RELATIVE_PATHS=SceneSaver::FLAG_RELATIVE_PATHS,
- SAVE_FLAG_BUNDLE_RESOURCES=SceneSaver::FLAG_BUNDLE_RESOURCES,
- SAVE_FLAG_BUNDLE_INSTANCED_SCENES=SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES,
- SAVE_FLAG_OMIT_EDITOR_PROPERTIES=SceneSaver::FLAG_OMIT_EDITOR_PROPERTIES,
- SAVE_FLAG_SAVE_BIG_ENDIAN=SceneSaver::FLAG_SAVE_BIG_ENDIAN
- };
-
- Node* load(const String& p_scene);
- Error save(const String& p_path, Node *p_scene,int p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>());
- Ref<SceneInteractiveLoader> load_interactive(const String& p_scene);
-
- SceneIO() {}
-};
-
-#endif
-#endif // SCENE_BINDS_H
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 1d99eb6d1f..af5e6d4165 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -41,8 +41,8 @@ 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");
+ 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");
@@ -67,6 +67,7 @@ SceneStringNames::SceneStringNames() {
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 +75,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 +99,8 @@ 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");
_input_event=StaticCString::create("_input_event");
@@ -147,4 +148,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..14e5e83b8d 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -56,13 +56,14 @@ public:
StringName _input_event;
StringName item_rect_changed;
StringName shader_shader;
- StringName enter_scene;
- StringName exit_scene;
+ 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;
@@ -89,12 +90,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 +120,8 @@ public:
StringName enter_camera;
StringName exit_camera;
- StringName _body_enter_scene;
- StringName _body_exit_scene;
+ StringName _body_enter_tree;
+ StringName _body_exit_tree;
StringName changed;
StringName _shader_changed;
@@ -155,6 +159,7 @@ public:
StringName _mouse_enter;
StringName _mouse_exit;
+ StringName frame_changed;
};
diff --git a/servers/SCsub b/servers/SCsub
index 1a858533b7..3871c30cfa 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -12,7 +12,7 @@ SConscript('audio/SCsub');
SConscript('spatial_sound/SCsub');
SConscript('spatial_sound_2d/SCsub');
-lib = env.Library("servers",env.servers_sources, LIBSUFFIX=env['platform_libsuffix'])
+lib = env.Library("servers",env.servers_sources)
env.Prepend(LIBS=[lib])
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/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp
index 4a303d3fdd..5938e716e9 100644
--- a/servers/physics/area_pair_sw.cpp
+++ b/servers/physics/area_pair_sw.cpp
@@ -67,7 +67,6 @@ void AreaPairSW::solve(float p_step) {
AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape) {
-
body=p_body;
area=p_area;
body_shape=p_body_shape;
@@ -75,6 +74,8 @@ AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_are
colliding=false;
body->add_constraint(this,0);
area->add_constraint(this);
+ if (p_body->get_mode()==PhysicsServer::BODY_MODE_KINEMATIC)
+ p_body->set_active(true);
}
diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp
index 8192a98400..4c9ac814be 100644
--- a/servers/physics/area_sw.cpp
+++ b/servers/physics/area_sw.cpp
@@ -148,8 +148,6 @@ void AreaSW::call_queries() {
return;
}
-
-
for (Map<BodyKey,BodyState>::Element *E=monitored_bodies.front();E;E=E->next()) {
if (E->get().state==0)
@@ -182,8 +180,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move
point_attenuation=1;
density=0.1;
priority=0;
- ray_pickable=false;
-
+ set_ray_pickable(false);
+ monitor_callback_id=0;
}
diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h
index a864055d17..c0c6e5c2ae 100644
--- a/servers/physics/area_sw.h
+++ b/servers/physics/area_sw.h
@@ -48,7 +48,6 @@ class AreaSW : public CollisionObjectSW{
float point_attenuation;
float density;
int priority;
- bool ray_pickable;
ObjectID monitor_callback_id;
StringName monitor_callback_method;
@@ -139,8 +138,6 @@ public:
_FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); }
_FORCE_INLINE_ const Set<ConstraintSW*>& get_constraints() const { return constraints; }
- _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; }
- _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index d112afa8e2..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)) {
+ 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;
+ }
@@ -267,6 +327,14 @@ bool BodyPairSW::setup(float p_step) {
B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crA);
}
+ if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC)) {
+ c.active=false;
+ collided=false;
+ continue;
+
+ }
+
+
c.active=true;
// Precompute normal mass, tangent mass, and bias.
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 0fd754ba25..725a440b59 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -185,6 +185,7 @@ float BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
void BodySW::set_mode(PhysicsServer::BodyMode p_mode) {
+ PhysicsServer::BodyMode prev=mode;
mode=p_mode;
switch(p_mode) {
@@ -196,8 +197,13 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) {
_inv_mass=0;
_set_static(p_mode==PhysicsServer::BODY_MODE_STATIC);
//set_active(p_mode==PhysicsServer::BODY_MODE_KINEMATIC);
+ set_active(p_mode==PhysicsServer::BODY_MODE_KINEMATIC && contacts.size());
linear_velocity=Vector3();
angular_velocity=Vector3();
+ if (mode==PhysicsServer::BODY_MODE_KINEMATIC && prev!=mode) {
+ first_time_kinematic=true;
+ }
+
} break;
case PhysicsServer::BODY_MODE_RIGID: {
@@ -237,6 +243,11 @@ void BodySW::set_state(PhysicsServer::BodyState p_state, const Variant& p_varian
new_transform=p_variant;
//wakeup_neighbours();
set_active(true);
+ if (first_time_kinematic) {
+ _set_transform(p_variant);
+ _set_inv_transform(get_transform().affine_inverse());
+ first_time_kinematic=false;
+ }
} else if (mode==PhysicsServer::BODY_MODE_STATIC) {
_set_transform(p_variant);
@@ -460,8 +471,8 @@ void BodySW::integrate_velocities(real_t p_step) {
if (mode==PhysicsServer::BODY_MODE_KINEMATIC) {
_set_transform(new_transform,false);
- _set_inv_transform(new_transform.affine_inverse()); ;
- if (linear_velocity==Vector3() && angular_velocity==Vector3())
+ _set_inv_transform(new_transform.affine_inverse());
+ if (contacts.size()==0 && linear_velocity==Vector3() && angular_velocity==Vector3())
set_active(false); //stopped moving, deactivate
return;
@@ -668,6 +679,7 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda
island_step=0;
island_next=NULL;
island_list_next=NULL;
+ first_time_kinematic=false;
_set_static(false);
density=0;
contact_count=0;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 6317186d5f..ee3c76e455 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -74,6 +74,7 @@ class BodySW : public CollisionObjectSW {
bool continuous_cd;
bool can_sleep;
+ bool first_time_kinematic;
void _update_inertia();
virtual void _shapes_changed();
Transform new_transform;
@@ -137,7 +138,7 @@ public:
_FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.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; }
+ _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);}
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp
index f34aa19cae..c8e1fc4022 100644
--- a/servers/physics/collision_object_sw.cpp
+++ b/servers/physics/collision_object_sw.cpp
@@ -217,4 +217,5 @@ CollisionObjectSW::CollisionObjectSW(Type p_type) {
space=NULL;
instance_id=0;
layer_mask=1;
+ ray_pickable=true;
}
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index e717cc257c..788292ad2a 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -59,6 +59,9 @@ private:
BroadPhaseSW::ID bpid;
AABB aabb_cache; //for rayqueries
ShapeSW *shape;
+ bool trigger;
+
+ Shape() { trigger=false; }
};
Vector<Shape> shapes;
@@ -94,6 +97,9 @@ protected:
virtual void _shapes_changed()=0;
void _set_space(SpaceSW *space);
+ bool ray_pickable;
+
+
CollisionObjectSW(Type p_type);
public:
@@ -119,6 +125,11 @@ public:
_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ SpaceSW* get_space() const { return space; }
+ _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; }
+ _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
+
+ _FORCE_INLINE_ void set_shape_as_trigger(int p_idx,bool p_enable) { shapes[p_idx].trigger=p_enable; }
+ _FORCE_INLINE_ bool is_shape_set_as_trigger(int p_idx) const { return shapes[p_idx].trigger; }
_FORCE_INLINE_ void set_layer_mask(uint32_t p_mask) { layer_mask=p_mask; }
_FORCE_INLINE_ uint32_t get_layer_mask() const { return layer_mask; }
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/constraint_sw.h b/servers/physics/constraint_sw.h
index 1be96422e1..5e79c4b54c 100644
--- a/servers/physics/constraint_sw.h
+++ b/servers/physics/constraint_sw.h
@@ -38,12 +38,13 @@ class ConstraintSW {
uint64_t island_step;
ConstraintSW *island_next;
ConstraintSW *island_list_next;
+ int priority;
RID self;
protected:
- ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; }
+ ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; priority=1; }
public:
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
@@ -62,6 +63,9 @@ public:
_FORCE_INLINE_ BodySW **get_body_ptr() const { return _body_ptr; }
_FORCE_INLINE_ int get_body_count() const { return _body_count; }
+ _FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
+ _FORCE_INLINE_ int get_priority() const { return priority; }
+
virtual bool setup(float p_step)=0;
virtual void solve(float p_step)=0;
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 043d2149fe..cfe5a73ce1 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -540,6 +540,8 @@ void PhysicsServerSW::body_set_shape_as_trigger(RID p_body, int p_shape_idx,bool
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ ERR_FAIL_INDEX(p_shape_idx,body->get_shape_count());
+ body->set_shape_as_trigger(p_shape_idx,p_enable);
}
@@ -547,10 +549,9 @@ bool PhysicsServerSW::body_is_shape_set_as_trigger(RID p_body, int p_shape_idx)
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,false);
+ ERR_FAIL_INDEX_V(p_shape_idx,body->get_shape_count(),false);
- // todo ?
-
- return false;
+ body->is_shape_set_as_trigger(p_shape_idx);
}
@@ -769,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);
};
@@ -836,6 +837,22 @@ void PhysicsServerSW::body_set_force_integration_callback(RID p_body,Object *p_r
}
+void PhysicsServerSW::body_set_ray_pickable(RID p_body,bool p_enable) {
+
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_ray_pickable(p_enable);
+
+}
+
+bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const{
+
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body,false);
+ return body->is_ray_pickable();
+
+}
+
/* JOINT API */
@@ -1000,6 +1017,21 @@ bool PhysicsServerSW::hinge_joint_get_flag(RID p_joint,HingeJointFlag p_flag) co
return hinge_joint->get_flag(p_flag);
}
+void PhysicsServerSW::joint_set_solver_priority(RID p_joint,int p_priority) {
+
+ JointSW *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ joint->set_priority(p_priority);
+}
+
+int PhysicsServerSW::joint_get_solver_priority(RID p_joint) const{
+
+ JointSW *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint,0);
+ return joint->get_priority();
+
+}
+
PhysicsServerSW::JointType PhysicsServerSW::joint_get_type(RID p_joint) const {
JointSW *joint = joint_owner.get(p_joint);
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 76e5aecf55..6609a78662 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -201,6 +201,9 @@ public:
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
+ virtual void body_set_ray_pickable(RID p_body,bool p_enable);
+ virtual bool body_is_ray_pickable(RID p_body) const;
+
/* JOINT API */
virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B);
@@ -244,6 +247,9 @@ public:
virtual JointType joint_get_type(RID p_joint) const;
+ virtual void joint_set_solver_priority(RID p_joint,int p_priority);
+ virtual int joint_get_solver_priority(RID p_joint) const;
+
#if 0
virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value);
virtual real_t joint_get_param(RID p_joint,JointParam p_param) const;
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 68d6b464ab..4e8b60b86b 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -71,12 +71,13 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
real_t min_d=1e10;
+
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 (space->intersection_query_results[i]->get_type()==CollisionObjectSW::TYPE_AREA && !(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
+ if (!(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
continue;
if (p_exclude.has( space->intersection_query_results[i]->get_self()))
@@ -97,6 +98,8 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) {
+
+
Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point=xform.xform(shape_point);
diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp
index 6d95804875..b7d06d207b 100644
--- a/servers/physics/step_sw.cpp
+++ b/servers/physics/step_sw.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "step_sw.h"
-
+#include "joints_sw.h"
void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island) {
@@ -68,14 +68,41 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){
- for(int i=0;i<p_iterations;i++) {
+ int at_priority=1;
- ConstraintSW *ci=p_island;
- while(ci) {
- ci->solve(p_delta);
- ci=ci->get_island_next();
+ while(p_island) {
+
+ for(int i=0;i<p_iterations;i++) {
+
+ ConstraintSW *ci=p_island;
+ while(ci) {
+ ci->solve(p_delta);
+ ci=ci->get_island_next();
+ }
+ }
+
+ at_priority++;
+
+ {
+ ConstraintSW *ci=p_island;
+ ConstraintSW *prev=NULL;
+ while(ci) {
+ if (ci->get_priority()<at_priority) {
+ if (prev) {
+ prev->set_island_next(ci->get_island_next()); //remove
+ } else {
+ p_island=ci->get_island_next();
+ }
+ } else {
+
+ prev=ci;
+ }
+
+ ci=ci->get_island_next();
+ }
}
}
+
}
void StepSW::_check_suspend(BodySW *p_island,float p_delta) {
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index 58035eb656..2e911288ae 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -99,7 +99,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 +115,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;
}
@@ -180,7 +182,9 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this),
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;
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index 0eda1050fa..d94b2f9ccf 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -47,7 +47,8 @@ class Area2DSW : public CollisionObject2DSW{
Vector2 gravity_vector;
bool gravity_is_point;
float point_attenuation;
- float density;
+ float linear_damp;
+ float angular_damp;
int priority;
ObjectID monitor_callback_id;
@@ -128,8 +129,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; }
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 35286bdb67..1c7f73db5e 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -75,6 +75,8 @@ AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body,int p_body_shape, Area2DSW *p_area,i
colliding=false;
body->add_constraint(this,0);
area->add_constraint(this);
+ if (p_body->get_mode()==Physics2DServer::BODY_MODE_KINEMATIC) //need to be active to process pair
+ p_body->set_active(true);
}
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index f10cdadf4e..1cfe9a6ab9 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:{}
}
@@ -176,6 +204,7 @@ float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) {
+ Physics2DServer::BodyMode prev=mode;
mode=p_mode;
switch(p_mode) {
@@ -186,9 +215,12 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) {
_set_inv_transform(get_transform().affine_inverse());
_inv_mass=0;
_set_static(p_mode==Physics2DServer::BODY_MODE_STATIC);
- //set_active(p_mode==Physics2DServer::BODY_MODE_KINEMATIC);
+ set_active(p_mode==Physics2DServer::BODY_MODE_KINEMATIC && contacts.size());
linear_velocity=Vector2();
angular_velocity=0;
+ if (mode==Physics2DServer::BODY_MODE_KINEMATIC && prev!=mode) {
+ first_time_kinematic=true;
+ }
} break;
case Physics2DServer::BODY_MODE_RIGID: {
@@ -226,9 +258,15 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va
if (mode==Physics2DServer::BODY_MODE_KINEMATIC) {
- new_transform=p_variant;
+
+ new_transform=p_variant;
//wakeup_neighbours();
set_active(true);
+ if (first_time_kinematic) {
+ _set_transform(p_variant);
+ _set_inv_transform(get_transform().affine_inverse());
+ first_time_kinematic=false;
+ }
} else if (mode==Physics2DServer::BODY_MODE_STATIC) {
_set_transform(p_variant);
_set_inv_transform(get_transform().affine_inverse());
@@ -346,6 +384,8 @@ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) {
} else {
gravity = p_area->get_gravity_vector() * p_area->get_gravity();
}
+
+ gravity*=gravity_scale;
}
void Body2DSW::integrate_forces(real_t p_step) {
@@ -369,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;
@@ -385,10 +434,10 @@ void Body2DSW::integrate_forces(real_t p_step) {
motion = new_transform.elements[2] - get_transform().elements[2];
do_motion=true;
- for(int i=0;i<get_shape_count();i++) {
- set_shape_kinematic_advance(i,Vector2());
- set_shape_kinematic_retreat(i,0);
- }
+ //for(int i=0;i<get_shape_count();i++) {
+ // set_shape_kinematic_advance(i,Vector2());
+ // set_shape_kinematic_retreat(i,0);
+ //}
} else {
if (!omit_force_integration) {
@@ -398,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;
@@ -434,7 +483,7 @@ void Body2DSW::integrate_forces(real_t p_step) {
}
current_area=NULL; // clear the area, so it is set in the next frame
- contact_count=0;
+ contact_count=0;
}
@@ -449,8 +498,8 @@ void Body2DSW::integrate_velocities(real_t p_step) {
if (mode==Physics2DServer::BODY_MODE_KINEMATIC) {
_set_transform(new_transform,false);
- _set_inv_transform(new_transform.affine_inverse()); ;
- if (linear_velocity==Vector2() && angular_velocity==0)
+ _set_inv_transform(new_transform.affine_inverse());
+ if (contacts.size()==0 && linear_velocity==Vector2() && angular_velocity==0)
set_active(false); //stopped moving, deactivate
return;
}
@@ -507,6 +556,7 @@ void Body2DSW::call_queries() {
Variant v=dbs;
const Variant *vp[2]={&v,&fi_callback->callback_udata};
+
Object *obj = ObjectDB::get_instance(fi_callback->id);
if (!obj) {
@@ -590,8 +640,14 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti
island_next=NULL;
island_list_next=NULL;
_set_static(false);
- density=0;
+ first_time_kinematic=false;
+ 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 ffe47e0267..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;
@@ -72,6 +80,7 @@ class Body2DSW : public CollisionObject2DSW {
bool omit_force_integration;
bool active;
bool can_sleep;
+ bool first_time_kinematic;
void _update_inertia();
virtual void _shapes_changed();
Matrix32 new_transform;
@@ -134,7 +143,8 @@ public:
_FORCE_INLINE_ void add_area(Area2DSW *p_area) { areas.insert(AreaCMP(p_area)); }
_FORCE_INLINE_ void remove_area(Area2DSW *p_area) { areas.erase(AreaCMP(p_area)); }
- _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; }
+ _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; if (mode==Physics2DServer::BODY_MODE_KINEMATIC && p_size) set_active(true);}
+
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
@@ -209,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();
@@ -217,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);
@@ -304,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
@@ -334,6 +353,8 @@ public:
virtual Vector2 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_pos; }
virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; }
virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; }
+ virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Variant()); return body->get_shape_metadata(body->contacts[p_contact_idx].collider_shape); }
+
virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; }
virtual Physics2DDirectSpaceState* get_space_state();
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index ee169cde28..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;
}
@@ -234,7 +234,7 @@ bool BodyPair2DSW::setup(float p_step) {
//cannot collide
- 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()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC)) {
+ 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()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) {
collided=false;
return false;
}
@@ -343,9 +343,11 @@ bool BodyPair2DSW::setup(float p_step) {
}
}
- if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B)) {
+ if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC)) {
c.active=false;
collided=false;
+ continue;
+
}
// Precompute normal mass, tangent mass, and bias.
@@ -476,6 +478,7 @@ BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A,Body2DSW *p_B, int p_sha
BodyPair2DSW::~BodyPair2DSW() {
+
A->remove_constraint(this);
B->remove_constraint(this);
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 277a286144..d0443f8110 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -55,6 +55,14 @@ void CollisionObject2DSW::set_shape(int p_index,Shape2DSW *p_shape){
_shapes_changed();
}
+
+void CollisionObject2DSW::set_shape_metadata(int p_index,const Variant& p_metadata) {
+
+ ERR_FAIL_INDEX(p_index,shapes.size());
+ shapes[p_index].metadata=p_metadata;
+
+}
+
void CollisionObject2DSW::set_shape_transform(int p_index,const Matrix32& p_transform){
ERR_FAIL_INDEX(p_index,shapes.size());
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index cc7f8f50bd..00ad361245 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -55,10 +55,9 @@ private:
BroadPhase2DSW::ID bpid;
Rect2 aabb_cache; //for rayqueries
Shape2DSW *shape;
- Vector2 kinematic_advance;
- float kinematic_retreat;
+ Variant metadata;
bool trigger;
- Shape() { trigger=false; kinematic_retreat=0; }
+ Shape() { trigger=false; }
};
Vector<Shape> shapes;
@@ -99,17 +98,15 @@ public:
void add_shape(Shape2DSW *p_shape,const Matrix32& p_transform=Matrix32());
void set_shape(int p_index,Shape2DSW *p_shape);
void set_shape_transform(int p_index,const Matrix32& p_transform);
+ void set_shape_metadata(int p_index,const Variant& p_metadata);
+
+
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
_FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { return shapes[p_index].shape; }
_FORCE_INLINE_ const Matrix32& get_shape_transform(int p_index) const { return shapes[p_index].xform; }
_FORCE_INLINE_ const Matrix32& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
_FORCE_INLINE_ const Rect2& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
-
- _FORCE_INLINE_ void set_shape_kinematic_advance(int p_index,const Vector2& p_advance) { shapes[p_index].kinematic_advance=p_advance; }
- _FORCE_INLINE_ Vector2 get_shape_kinematic_advance(int p_index) const { return shapes[p_index].kinematic_advance; }
-
- _FORCE_INLINE_ void set_shape_kinematic_retreat(int p_index,float p_retreat) { shapes[p_index].kinematic_retreat=p_retreat; }
- _FORCE_INLINE_ float get_shape_kinematic_retreat(int p_index) const { return shapes[p_index].kinematic_retreat; }
+ _FORCE_INLINE_ const Variant& get_shape_metadata(int p_index) const { return shapes[p_index].metadata; }
_FORCE_INLINE_ Matrix32 get_transform() const { return transform; }
_FORCE_INLINE_ Matrix32 get_inv_transform() const { return inv_transform; }
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 09fa3f9b6a..be49955055 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;
@@ -548,6 +563,22 @@ void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, co
body->set_shape_transform(p_shape_idx,p_transform);
}
+void Physics2DServerSW::body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_shape_metadata(p_shape_idx,p_metadata);
+}
+
+
+Variant Physics2DServerSW::body_get_shape_metadata(RID p_body, int p_shape_idx) const {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body,Variant());
+ return body->get_shape_metadata(p_shape_idx);
+}
+
+
int Physics2DServerSW::body_get_shape_count(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
@@ -844,6 +875,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) {
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 7ffffe669f..e9c499aaff 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;
@@ -149,10 +151,14 @@ public:
virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32());
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape);
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform);
+ virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata);
+
virtual int body_get_shape_count(RID p_body) const;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const;
virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const;
+ virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const;
+
virtual void body_remove_shape(RID p_body, int p_shape_idx);
virtual void body_clear_shapes(RID p_body);
@@ -201,6 +207,13 @@ 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);
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 012c4ed404..336eec73b5 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -131,7 +131,7 @@ 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;
}
@@ -180,7 +180,7 @@ bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end
}
-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
}
@@ -237,10 +237,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());
}
@@ -312,9 +314,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) {
@@ -377,9 +380,9 @@ bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2&
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;
}
@@ -499,9 +502,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;
}
@@ -610,16 +613,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) {
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index 8500a6194f..51ece9fc7e 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -84,7 +84,7 @@ public:
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;
@@ -173,7 +173,7 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) 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;
@@ -215,7 +215,7 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) 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;
@@ -262,7 +262,7 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) 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;
@@ -299,7 +299,7 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) 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;
@@ -338,20 +338,25 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) 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 )));
- r_min = distance - length;
- r_max = distance + length;
+ if (d>r_max)
+ r_max=d;
+ if (d<r_min)
+ r_min=d;
+
+ }
}
@@ -420,7 +425,7 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) 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;
@@ -482,7 +487,7 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) 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;
@@ -570,7 +575,7 @@ public:
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 21a99cd4b2..f2ed74ffbf 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -98,7 +98,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);
@@ -126,6 +126,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec
if (r_result.collider_id!=0)
r_result.collider=ObjectDB::get_instance(r_result.collider_id);
r_result.normal=res_normal;
+ r_result.metadata=res_obj->get_shape_metadata(res_shape);
r_result.position=res_point;
r_result.rid=res_obj->get_self();
r_result.shape=res_shape;
@@ -171,6 +172,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri
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++;
@@ -215,6 +217,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)) {
@@ -225,6 +237,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;
}
@@ -251,6 +271,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;
@@ -309,14 +352,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;
@@ -332,6 +384,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) {
@@ -339,17 +393,30 @@ 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;
rd->best_object=rd->object;
rd->best_shape=rd->shape;
+
}
@@ -382,6 +449,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);
@@ -399,6 +477,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape
r_info->normal=rcd.best_normal;
r_info->point=rcd.best_contact;
r_info->rid=rcd.best_object->get_self();
+ r_info->metadata=rcd.best_object->get_shape_metadata(rcd.best_shape);
if (rcd.best_object->get_type()==CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *body = static_cast<const Body2DSW*>(rcd.best_object);
@@ -433,6 +512,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) {
@@ -447,7 +527,6 @@ 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);
@@ -602,8 +681,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;
}
}
@@ -618,7 +696,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;
@@ -660,7 +737,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..7977b19063 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -93,7 +93,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 +141,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 da8ac5f9c8..07389bc912 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);
@@ -97,6 +102,7 @@ void Physics2DDirectBodyState::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id);
ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object);
ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape);
+ ObjectTypeDB::bind_method(_MD("get_contact_collider_shape_metadata:var","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata);
ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos);
ObjectTypeDB::bind_method(_MD("get_step"),&Physics2DDirectBodyState::get_step);
ObjectTypeDB::bind_method(_MD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces);
@@ -244,6 +250,7 @@ Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2& p_from, cons
d["collider"]=inters.collider;
d["shape"]=inters.shape;
d["rid"]=inters.rid;
+ d["metadata"]=inters.metadata;
return d;
}
@@ -262,6 +269,7 @@ Array Physics2DDirectSpaceState::_intersect_shape(const Ref<Physics2DShapeQueryP
d["collider_id"]=sr[i].collider_id;
d["collider"]=sr[i].collider;
d["shape"]=sr[i].shape;
+ d["metadata"]=sr[i].metadata;
ret[i]=d;
}
@@ -311,6 +319,7 @@ Dictionary Physics2DDirectSpaceState::_get_rest_info(const Ref<Physics2DShapeQue
r["collider_id"]=sri.collider_id;
r["shape"]=sri.shape;
r["linear_velocity"]=sri.linear_velocity;
+ r["metadata"]=sri.metadata;
return r;
}
@@ -412,8 +421,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);
@@ -446,10 +455,12 @@ void Physics2DServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Matrix32()));
ObjectTypeDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape);
ObjectTypeDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform);
+ ObjectTypeDB::bind_method(_MD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata);
ObjectTypeDB::bind_method(_MD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count);
ObjectTypeDB::bind_method(_MD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape);
ObjectTypeDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform);
+ ObjectTypeDB::bind_method(_MD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata);
ObjectTypeDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape);
ObjectTypeDB::bind_method(_MD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes);
@@ -489,6 +500,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);
@@ -508,7 +526,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);
@@ -532,7 +550,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 );
@@ -547,6 +566,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 17a21e46a3..765cebf45f 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
@@ -71,6 +72,7 @@ public:
virtual ObjectID get_contact_collider_id(int p_contact_idx) const=0;
virtual Object* get_contact_collider_object(int p_contact_idx) const;
virtual int get_contact_collider_shape(int p_contact_idx) const=0;
+ virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const=0;
virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const=0;
virtual real_t get_step() const=0;
@@ -163,6 +165,7 @@ public:
ObjectID collider_id;
Object *collider;
int shape;
+ Variant metadata;
};
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)=0;
@@ -173,6 +176,8 @@ public:
ObjectID collider_id;
Object *collider;
int shape;
+ Variant metadata;
+
};
@@ -190,6 +195,7 @@ public:
ObjectID collider_id;
int shape;
Vector2 linear_velocity; //velocity at contact point
+ Variant metadata;
};
@@ -272,7 +278,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,
};
@@ -296,7 +301,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
};
@@ -360,10 +366,12 @@ public:
virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32())=0;
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape)=0;
virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform)=0;
+ virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata)=0;
virtual int body_get_shape_count(RID p_body) const=0;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const=0;
virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const=0;
+ virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const=0;
virtual void body_set_shape_as_trigger(RID p_body, int p_shape_idx,bool p_enable)=0;
virtual bool body_is_shape_set_as_trigger(RID p_body, int p_shape_idx) const=0;
@@ -394,6 +402,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,
};
@@ -407,7 +418,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;
@@ -431,6 +442,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;
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index dc8e4cc298..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);
@@ -520,6 +520,9 @@ void PhysicsServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant()));
+ ObjectTypeDB::bind_method(_MD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable);
+ ObjectTypeDB::bind_method(_MD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable);
+
/* JOINT API */
BIND_CONSTANT( JOINT_PIN );
@@ -627,6 +630,9 @@ void PhysicsServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
+ ObjectTypeDB::bind_method(_MD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority);
+ ObjectTypeDB::bind_method(_MD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority);
+
ObjectTypeDB::bind_method(_MD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof);
ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param);
@@ -649,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/physics_server.h b/servers/physics_server.h
index 25a89775a8..0c2542a66c 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -450,6 +450,10 @@ public:
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0;
+ virtual void body_set_ray_pickable(RID p_body,bool p_enable)=0;
+ virtual bool body_is_ray_pickable(RID p_body) const=0;
+
+
/* JOINT API */
enum JointType {
@@ -464,6 +468,8 @@ public:
virtual JointType joint_get_type(RID p_joint) const=0;
+ virtual void joint_set_solver_priority(RID p_joint,int p_priority)=0;
+ virtual int joint_get_solver_priority(RID p_joint) const=0;
virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B)=0;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index f8d38d15c0..a2b1b71f99 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -57,6 +57,7 @@ void register_server_types() {
ObjectTypeDB::register_virtual_type<Physics2DShapeQueryResult>();
ObjectTypeDB::register_type<Physics2DShapeQueryParameters>();
+ ObjectTypeDB::register_type<PhysicsShapeQueryParameters>();
ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>();
ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>();
ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>();
diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp
index 7ec29d32cb..d00deb3912 100644
--- a/servers/spatial_sound/spatial_sound_server_sw.cpp
+++ b/servers/spatial_sound/spatial_sound_server_sw.cpp
@@ -879,10 +879,13 @@ void SpatialSoundServerSW::update(float p_delta) {
float volume_attenuation = 0.0;
float air_absorption_hf_cutoff = 0.0;
float air_absorption = 0.0;
- float pitch_scale=0.0;
+ float pitch_scale=1.0;
Vector3 panning;
+ //print_line("listeners: "+itos(space->listeners.size()));
+
+
for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
Listener *listener=listener_owner.get(L->get());
@@ -899,9 +902,11 @@ void SpatialSoundServerSW::update(float p_delta) {
float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP];
float attenuation=1;
+ //print_line("DIST MIN: "+rtos(distance_min));
+ //print_line("DIST MAX: "+rtos(distance_max));
if (distance_max>0) {
distance = CLAMP(distance,distance_min,distance_max);
- attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16));
+ attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
}
float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];
@@ -945,7 +950,7 @@ void SpatialSoundServerSW::update(float p_delta) {
air_absorption+=weight*absorption;
air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff;
panning+=vpanning*weight;
- pitch_scale+=pscale*weight;
+ //pitch_scale+=pscale*weight;
}
@@ -991,8 +996,8 @@ void SpatialSoundServerSW::update(float p_delta) {
reverb_send*=volume_scale;
int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE];
- if (mix_rate<=0) {
+ if (mix_rate<=0) {
ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param.");
to_disable.push_back(ActiveVoice(source,voice)); // oh well..
continue; //invalid mix rate, disabling
diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
index e3c8aba758..2aab0e7dc9 100644
--- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
+++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
@@ -904,7 +904,7 @@ void SpatialSound2DServerSW::update(float p_delta) {
if (distance_max>0) {
distance = CLAMP(distance,distance_min,distance_max);
- attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16));
+ attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
}
float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp
index e160b4dccc..c3dcd83a31 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 */
@@ -96,8 +96,14 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
} else {
uv_str=_TEXUVSTR(VS::FIXED_MATERIAL_PARAM_NORMAL);
}
- scode+="vec3 normal=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n";
- scode+="NORMAL = mix( NORMAL,mat3(TANGENT,BINORMAL,NORMAL) * normal, fmp_normal);\n";
+ if (p_key.use_xy_normalmap) {
+ scode+="vec2 ywnormal=tex( fmp_normal_tex,"+uv_str+").wy * vec2(2.0,2.0) - vec2(1.0,1.0);\n";
+ scode+="NORMALMAP=vec3(ywnormal,sqrt(1 - (ywnormal.x * ywnormal.x) - (ywnormal.y * ywnormal.y) ));\n";
+ } else {
+ scode+="NORMALMAP=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n";
+ }
+ scode+="NORMALMAP_DEPTH=fmp_normal;\n";
+
code+=scode;
}
@@ -323,6 +329,7 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags
case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: fm.use_color_array=p_enabled; break;
case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: fm.use_pointsize=p_enabled; break;
case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: fm.discard_alpha=p_enabled; break;
+ case VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP: fm.use_xy_normalmap=p_enabled; break;
}
if (!fm.dirty_list.in_list())
@@ -341,6 +348,8 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags
case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: return fm.use_color_array;; break;
case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: return fm.use_pointsize;; break;
case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: return fm.discard_alpha;; break;
+ case VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP: return fm.use_xy_normalmap;; break;
+
}
@@ -355,12 +364,13 @@ RID Rasterizer::fixed_material_create() {
FixedMaterial &fm=*fixed_materials[mat];
fm.self=mat;
fm.get_key();
+ material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true);
for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) {
material_set_param(mat,_fixed_material_param_names[i],fm.param[i]); //must be there
}
fixed_material_dirty_list.add(&fm.dirty_list);
- //print_line("FMC: "+itos(mat.get_id()));
+ //print_line("FMC: "+itos(mat.get_id()));
return mat;
}
@@ -558,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());
@@ -610,6 +621,10 @@ 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);
+
}
RID Rasterizer::create_overdraw_debug_material() {
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 5b07c633c3..92c7b8ac14 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();
@@ -56,6 +59,7 @@ protected:
bool use_color_array:1;
bool use_pointsize:1;
bool discard_alpha:1;
+ bool use_xy_normalmap:1;
bool valid:1;
};
@@ -83,6 +87,7 @@ protected:
bool use_color_array;
bool discard_alpha;
bool use_pointsize;
+ bool use_xy_normalmap;
float point_size;
Transform uv_xform;
VS::FixedMaterialLightShader light_shader;
@@ -102,6 +107,7 @@ protected:
k.use_alpha=use_alpha;
k.use_color_array=use_color_array;
k.use_pointsize=use_pointsize;
+ k.use_xy_normalmap=use_xy_normalmap;
k.discard_alpha=discard_alpha;
k.light_shader=light_shader;
k.valid=true;
@@ -123,6 +129,7 @@ protected:
use_color_array=false;
use_pointsize=false;
discard_alpha=false;
+ use_xy_normalmap=false;
point_size=1.0;
light_shader=VS::FIXED_MATERIAL_LIGHT_SHADER_LAMBERT;
for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) {
@@ -183,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 */
@@ -199,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;
@@ -499,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;
@@ -510,6 +524,7 @@ public:
float lightmap_multiplier;
int octree_steps;
Vector2 octree_tex_pixel_size;
+ Vector2 light_tex_pixel_size;
};
struct InstanceData {
@@ -517,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;
@@ -550,7 +566,279 @@ public:
CANVAS_RECT_FLIP_H=4,
CANVAS_RECT_FLIP_V=8
};
-
+
+ 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;
+ Vector<Command*> commands;
+ mutable bool custom_rect;
+ mutable bool rect_dirty;
+ mutable Rect2 rect;
+ CanvasItem*next;
+ RID shader;
+ Map<StringName,Variant> shader_param;
+ uint32_t shader_version;
+
+
+ float final_opacity;
+ Matrix32 final_transform;
+ Rect2 final_clip_rect;
+ CanvasItem* final_clip_owner;
+ CanvasItem* shader_owner;
+ ViewportRender *vp_render;
+
+ 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; shader_owner=NULL;}
+ CanvasItem() { 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; shader_version=0; shader_owner=NULL;}
+ virtual ~CanvasItem() { clear(); }
+ };
+
+
+ CanvasItemDrawViewportFunc draw_viewport_func;
+
+
virtual void canvas_begin()=0;
virtual void canvas_disable_blending()=0;
virtual void canvas_set_opacity(float p_opacity)=0;
@@ -564,7 +852,10 @@ 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)=0;
+
+
/* ENVIRONMENT */
@@ -582,6 +873,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*/
diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp
index 637c251cf1..6c1b6697c1 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 */
@@ -1607,6 +1622,11 @@ void RasterizerDummy::canvas_set_transform(const Matrix32& p_transform) {
}
+void RasterizerDummy::canvas_render_items(CanvasItem *p_item_list) {
+
+
+}
+
/* ENVIRONMENT */
RID RasterizerDummy::environment_create() {
@@ -1679,6 +1699,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 {
@@ -1816,6 +1848,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..c72149f88f 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();
@@ -697,6 +710,8 @@ 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);
+
/* ENVIRONMENT */
virtual RID environment_create();
@@ -713,6 +728,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*/
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 14d35e89b1..9a76a009a9 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -436,7 +436,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 +466,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;
}
}
@@ -765,16 +768,20 @@ 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}},
{"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 +860,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 +900,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}},
@@ -952,10 +963,16 @@ 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}},
@@ -1038,10 +1055,12 @@ 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},
+ { "NORMALMAP", TYPE_VEC3},
+ { "NORMALMAP_DEPTH", TYPE_FLOAT},
{ "UV", TYPE_VEC2},
{ "UV2", TYPE_VEC2},
{ "COLOR", TYPE_VEC4},
@@ -1087,6 +1106,61 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={
};
+
+
+const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={
+
+ { "SRC_VERTEX", TYPE_VEC2},
+ { "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[]={
+
+ { "COLOR", TYPE_VEC4},
+ { "NORMAL", TYPE_VEC3},
+ { "LIGHT_DIR", TYPE_VEC2},
+ { "LIGHT_DISTANCE", TYPE_FLOAT},
+ { "LIGHT", TYPE_VEC3},
+ { "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},
@@ -1199,9 +1273,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;
@@ -2437,6 +2527,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) {
@@ -2483,6 +2594,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));
@@ -2531,6 +2645,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..f79c219d85 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -105,6 +105,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,
};
@@ -376,6 +379,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 21ecd4030d..dc0bff4cf4 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() {
@@ -1202,7 +1392,7 @@ RID VisualServerRaster::camera_create() {
}
void VisualServerRaster::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) {
- VS_CHANGED;
+ VS_CHANGED
Camera *camera = camera_owner.get( p_camera );
ERR_FAIL_COND(!camera);
camera->type=Camera::PERSPECTIVE;
@@ -1226,7 +1416,7 @@ void VisualServerRaster::camera_set_transform(RID p_camera,const Transform& p_tr
VS_CHANGED;
Camera *camera = camera_owner.get( p_camera );
ERR_FAIL_COND(!camera);
- camera->transform=p_transform;
+ camera->transform=p_transform.orthonormalized();
}
@@ -1786,6 +1976,17 @@ void VisualServerRaster::scenario_set_environment(RID p_scenario, RID p_environm
}
+void VisualServerRaster::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
+
+ VS_CHANGED;
+
+ Scenario *scenario = scenario_owner.get(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ scenario->fallback_environment=p_environment;
+
+
+}
+
RID VisualServerRaster::scenario_get_environment(RID p_scenario, RID p_environment) const{
const Scenario *scenario = scenario_owner.get(p_scenario);
@@ -1932,6 +2133,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();
}
@@ -1981,6 +2196,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();
@@ -2596,11 +2821,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;
@@ -2736,6 +3000,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;
@@ -2848,6 +3119,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: {}
}
@@ -3071,129 +3352,6 @@ 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);
- }
-
- rect_dirty=false;
- return rect;
-}
void VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) {
@@ -3531,6 +3689,83 @@ 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_use_parent_shader(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_shader=p_enable;
+
+}
+
+void VisualServerRaster::canvas_item_set_shader(RID p_item, RID p_shader) {
+
+ VS_CHANGED;
+ CanvasItem *canvas_item = canvas_item_owner.get( p_item );
+ ERR_FAIL_COND(!canvas_item);
+ canvas_item->shader=p_shader;
+}
+
+RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{
+
+ CanvasItem *canvas_item = canvas_item_owner.get( p_item );
+ ERR_FAIL_COND_V(!canvas_item,RID());
+ return canvas_item->shader;
+
+}
+
+void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){
+
+ VS_CHANGED;
+ CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
+ ERR_FAIL_COND(!canvas_item);
+ if (p_value.get_type()==Variant::NIL)
+ canvas_item->shader_param.erase(p_param);
+ else
+ canvas_item->shader_param[p_param]=p_value;
+
+}
+Variant VisualServerRaster::canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const{
+
+ CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
+ ERR_FAIL_COND_V(!canvas_item,Variant());
+ if (!canvas_item->shader_param.has(p_param)) {
+ ERR_FAIL_COND_V(!canvas_item->shader.is_valid(),Variant());
+ return rasterizer->shader_get_default_param(canvas_item->shader,p_param);
+ }
+
+ return canvas_item->shader_param[p_param];
+}
+
+
+void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
+
+ VS_CHANGED;
+ CanvasItem *canvas_item = canvas_item_owner.get( p_item );
+ ERR_FAIL_COND(!canvas_item);
+ canvas_item->sort_y=p_enable;
+}
+
+
void VisualServerRaster::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
VS_CHANGED;
@@ -3742,6 +3977,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
@@ -3793,7 +4039,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());
@@ -4937,6 +5185,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)
@@ -4986,6 +5243,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)
@@ -5177,6 +5443,308 @@ 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_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) {
@@ -5228,6 +5796,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()));
@@ -5388,6 +5957,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
keep=true;
}
+
+
}
@@ -5400,6 +5971,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;
+ }
+ }
}
}
@@ -5479,7 +6057,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);
@@ -5500,15 +6078,31 @@ 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;
- else
+ else if (p_scenario->environment.is_valid())
environment=p_scenario->environment;
+ 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);
@@ -5551,7 +6145,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) {
+
+
+ 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]);
+ }
+
+}
+
+
+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_shader_owner) {
CanvasItem *ci = p_canvas_item;
@@ -5570,200 +6198,100 @@ 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_shader && p_shader_owner)
+ ci->shader_owner=p_shader_owner;
+ else {
+ p_shader_owner=ci;
+ ci->shader_owner=NULL;
}
- int s = ci->commands.size();
- bool reclip=false;
float opacity = ci->opacity * p_opacity;
-#ifndef ONTOP_DISABLED
- CanvasItem **child_items = ci->child_items.ptr();
+
int child_item_count=ci->child_items.size();
- int top_item_count=0;
- CanvasItem **top_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*));
+ CanvasItem **child_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*));
+ 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;
- }
-
- for(int i=0;i<child_item_count;i++) {
+ ci->final_clip_rect=global_rect;
+ ci->final_clip_owner=ci;
- if (child_items[i]->ontop)
- top_items[top_item_count++]=child_items[i];
- else {
- _render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
- }
+ } else {
+ ci->final_clip_owner=p_canvas_clip;
}
-#endif
-
- 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];
+ if (ci->sort_y) {
- 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: {
-
- 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 (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
- 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);
-
- } 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: {
-
- 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);
-
- } break;
-
- case CanvasItem::Command::TYPE_POLYGON_PTR: {
-
- 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: {
-
- 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;
- }
- 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;
- }
- }
- }
+ SortArray<CanvasItem*,CanvasItemPtrSort> sorter;
+ sorter.sort(child_items,child_item_count);
+ }
+ for(int i=0;i<child_item_count;i++) {
- } break;
- }
- }
- rasterizer->canvas_end_rect();
- }
+ 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_shader_owner);
}
- if (reclip) {
+ if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render) {
+ //something to draw?
+ ci->final_transform=xform;
+ ci->final_opacity=opacity * ci->self_opacity;
- rasterizer->canvas_set_clip(true,canvas_clip);
- }
+ if (ci->z_relative)
+ p_z=CLAMP(p_z+ci->z,CANVAS_ITEM_Z_MIN,CANVAS_ITEM_Z_MAX);
+ else
+ p_z=ci->z;
-#ifndef ONTOP_DISABLED
+ int zidx = p_z-CANVAS_ITEM_Z_MIN;
- for(int i=0;i<top_item_count;i++) {
+ if (z_last_list[zidx]) {
+ z_last_list[zidx]->next=ci;
+ z_last_list[zidx]=ci;
- _render_canvas_item(top_items[i],xform,p_clip_rect,opacity);
- }
+ } else {
+ z_list[zidx]=ci;
+ z_last_list[zidx]=ci;
+ }
-#else
- for(int i=0;i<p_canvas_item->child_items.size();i++) {
+ ci->next=NULL;
- _render_canvas_item(p_canvas_item->child_items[i],xform,p_clip_rect,opacity);
}
-#endif
+ for(int i=0;i<child_item_count;i++) {
- if (ci->clip) {
- rasterizer->canvas_set_clip(false,Rect2());
- canvas_clip=Rect2();
+ 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_shader_owner);
}
}
@@ -5773,29 +6301,61 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans
rasterizer->canvas_begin();
int l = p_canvas->child_items.size();
+ Canvas::ChildItem *ci=p_canvas->child_items.ptr();
+ bool has_mirror=false;
for(int i=0;i<l;i++) {
+ if (ci[i].mirror.x || ci[i].mirror.y) {
+ has_mirror=true;
+ break;
+ }
+ }
- 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);
+ Rect2 clip_rect(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height);
+ if (!has_mirror) {
- //mirroring (useful for scrolling backgrounds)
- if (ci.mirror.x!=0) {
+ 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];
- 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);
+ for(int i=0;i<z_range;i++) {
+ z_list[i]=NULL;
+ z_last_list[i]=NULL;
}
- if (ci.mirror.y!=0) {
-
- 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);
+ 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);
}
- 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);
+ for(int i=0;i<z_range;i++) {
+ if (!z_list[i])
+ continue;
+ rasterizer->canvas_render_items(z_list[i]);
}
+ } else {
+
+ for(int i=0;i<l;i++) {
+
+ Canvas::ChildItem& ci=p_canvas->child_items[i];
+ _render_canvas_item_tree(ci.item,p_transform,clip_rect);
+
+ //mirroring (useful for scrolling backgrounds)
+ if (ci.mirror.x!=0) {
+
+ Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0));
+ _render_canvas_item_tree(ci.item,xform2,clip_rect);
+ }
+ if (ci.mirror.y!=0) {
+
+ Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y));
+ _render_canvas_item_tree(ci.item,xform2,clip_rect);
+ }
+ 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);
+ }
+
+ }
}
}
@@ -5819,6 +6379,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 ||
@@ -5828,7 +6389,7 @@ 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);
}
@@ -5876,6 +6437,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
if (p_viewport->queue_capture) {
rasterizer->capture_viewport(&p_viewport->capture);
+ p_viewport->queue_capture = false;
}
//restore
@@ -5956,7 +6518,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));
@@ -5975,7 +6537,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);
}
@@ -6204,6 +6773,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 49e7996c59..6c4e15827a 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;
@@ -320,6 +362,7 @@ class VisualServerRaster : public VisualServer {
List<RID> directional_lights;
RID environment;
+ RID fallback_environment;
Instance *dirty_instances;
@@ -328,143 +371,44 @@ class VisualServerRaster : public VisualServer {
-
- 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 {
+ struct CanvasItem : public Rasterizer::CanvasItem {
- 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_shader;
+
- 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; }
- ~CanvasItem() { clear(); }
+
+ CanvasItem() {
+ E=NULL;
+ z=0;
+ opacity=1;
+ self_opacity=1;
+ sort_y=false;
+ use_parent_shader=false;
+ z_relative=true;
+ }
};
+ struct CanvasItemPtrSort {
+
+ _FORCE_INLINE_ bool operator()(const CanvasItem* p_left,const CanvasItem* p_right) const {
+
+ return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
+ }
+ };
struct Canvas {
@@ -594,6 +538,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;
@@ -629,6 +576,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;
@@ -649,8 +597,12 @@ 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_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);
+ 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);
+ 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_shader_owner);
void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform);
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);
@@ -700,6 +652,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();
@@ -944,12 +900,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();
@@ -1030,6 +1002,8 @@ public:
virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const;
+ virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
+
/* INSTANCING API */
@@ -1085,6 +1059,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;
@@ -1135,6 +1112,18 @@ public:
virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform);
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_shader(RID p_item, RID p_shader);
+ virtual RID canvas_item_get_shader(RID p_item) const;
+
+ virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable);
+
+
+ virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value);
+ virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const;
virtual void canvas_item_clear(RID p_item);
virtual void canvas_item_raise(RID p_item);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index f1ba4c453b..b59fdbc66a 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);
@@ -929,6 +947,7 @@ public:
FUNC2(camera_set_environment,RID,RID);
FUNC1RC(RID,camera_get_environment,RID);
+
FUNC2(camera_set_use_vertical_aspect,RID,bool);
FUNC2RC(bool,camera_is_using_vertical_aspect,RID,bool);
@@ -998,6 +1017,7 @@ public:
FUNC2(scenario_set_debug,RID,ScenarioDebugMode);
FUNC2(scenario_set_environment,RID, RID);
FUNC2RC(RID,scenario_get_environment,RID, RID);
+ FUNC2(scenario_set_fallback_environment,RID, RID);
/* INSTANCING API */
@@ -1053,6 +1073,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);
@@ -1107,6 +1130,19 @@ public:
FUNC2(canvas_item_add_set_blend_mode,RID, MaterialBlendMode );
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);
+
+ FUNC2(canvas_item_set_shader,RID, RID );
+ FUNC1RC(RID,canvas_item_get_shader,RID );
+
+ FUNC2(canvas_item_set_use_parent_shader,RID, bool );
+
+
+ FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&);
+ FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&);
+
FUNC1(canvas_item_clear,RID);
FUNC1(canvas_item_raise,RID);
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 9abfecaac6..e0238c8042 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -486,7 +486,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);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 8934fa7903..5721e7acf0 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -86,6 +86,10 @@ 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,
};
@@ -96,8 +100,10 @@ public:
TEXTURE_FLAG_MIPMAPS=1, /// Enable automatic mipmap generation - when available
TEXTURE_FLAG_REPEAT=2, /// Repeat texture (Tiling), otherwise Clamping
TEXTURE_FLAG_FILTER=4, /// Create texure with linear (or available) filter
- TEXTURE_FLAG_CUBEMAP=8,
- TEXTURE_FLAG_VIDEO_SURFACE=16,
+ TEXTURE_FLAG_ANISOTROPIC_FILTER=8,
+ TEXTURE_FLAG_CONVERT_TO_LINEAR=16,
+ TEXTURE_FLAG_CUBEMAP=2048,
+ TEXTURE_FLAG_VIDEO_SURFACE=4096,
TEXTURE_FLAGS_DEFAULT=TEXTURE_FLAG_REPEAT|TEXTURE_FLAG_MIPMAPS|TEXTURE_FLAG_FILTER
};
@@ -137,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;
@@ -148,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 */
@@ -166,6 +176,7 @@ public:
MATERIAL_FLAG_UNSHADED,
MATERIAL_FLAG_ONTOP,
MATERIAL_FLAG_LIGHTMAP_ON_UV2,
+ MATERIAL_FLAG_COLOR_ARRAY_SRGB,
MATERIAL_FLAG_MAX,
};
@@ -229,6 +240,7 @@ public:
FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,
FIXED_MATERIAL_FLAG_USE_POINT_SIZE,
FIXED_MATERIAL_FLAG_DISCARD_ALPHA,
+ FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP,
FIXED_MATERIAL_FLAG_MAX,
};
@@ -585,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 */
@@ -803,7 +838,7 @@ public:
virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode)=0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment)=0;
virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const=0;
-
+ virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment)=0;
/* INSTANCING API */
@@ -819,7 +854,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)
};
@@ -893,9 +929,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;
@@ -944,10 +984,21 @@ public:
virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform)=0;
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_clear(RID p_item)=0;
virtual void canvas_item_raise(RID p_item)=0;
+ virtual void canvas_item_set_shader(RID p_item, RID p_shader)=0;
+ virtual RID canvas_item_get_shader(RID p_item) const=0;
+
+ virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable)=0;
+
+ virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0;
+ virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=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 528ffbf3c3..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, LIBSUFFIX=env['platform_libsuffix'])
+ 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 e29888b433..97e9f5c36d 100644
--- a/tools/collada/collada.cpp
+++ b/tools/collada/collada.cpp
@@ -443,7 +443,10 @@ Vector<String> Collada::_read_string_array(XMLParser& parser) {
if (parser.get_node_type() == XMLParser::NODE_TEXT) {
// parse String data
String str = parser.get_node_data();
- array=str.split(" ",false);
+ array=str.split_spaces();
+ //for(int i=0;i<array.size();i++) {
+ // print_line(itos(i)+": "+array[i]);
+ //}
}
else
if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
@@ -2066,6 +2069,8 @@ void Collada::_parse_animation(XMLParser& parser) {
track.target=target;
}
+ print_line("TARGET: "+track.target);
+
state.animation_tracks.push_back(track);
if (!state.referenced_tracks.has(target))
@@ -2101,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"))
@@ -2144,6 +2151,7 @@ void Collada::_parse_scene(XMLParser& parser) {
if (name=="instance_visual_scene") {
state.root_visual_scene=_uri_to_id(parser.get_attribute_value("url"));
+ print_line("***ROOT VISUAL SCENE: "+state.root_visual_scene);
} if (name=="instance_physics_scene") {
state.root_physics_scene=_uri_to_id(parser.get_attribute_value("url"));
@@ -2242,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) {
- NodeSkeleton *sk = memnew( NodeSkeleton );
- *p_node=sk;
- sk->children.push_back(node);
- sk->parent=node->parent;
- node->parent=sk;
- _joint_set_owner(node,sk);
+ // 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;
+ }
+
+ 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) {
@@ -2317,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);
@@ -2513,6 +2530,9 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene,Node *p_node,Lis
ERR_FAIL_COND_V( !state.scene_map.has( nodeid ), false); //weird, it should have it...
NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
ERR_FAIL_COND_V(!nj,false);
+ if (!nj->owner) {
+ print_line("Has no owner: "+nj->name);
+ }
ERR_FAIL_COND_V( !nj->owner,false ); //weird, node should have a skeleton owner
NodeSkeleton *sk = nj->owner;
@@ -2615,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]);
}
@@ -2642,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 360f54ec05..f523d24e02 100644
--- a/tools/collada/collada.h
+++ b/tools/collada/collada.h
@@ -302,6 +302,7 @@ public:
Vector3 uv2;
Plane tangent;
Color color;
+ int uid;
struct Weight {
int bone_idx;
float weight;
@@ -331,21 +332,26 @@ public:
bool operator<(const Vertex& p_vert) const {
- if (vertex==p_vert.vertex) {
- if(normal==p_vert.normal) {
- if(uv==p_vert.uv) {
- if(uv2==p_vert.uv2) {
- return (color<p_vert.color);
+ if (uid==p_vert.uid) {
+ if (vertex==p_vert.vertex) {
+ if(normal==p_vert.normal) {
+ if(uv==p_vert.uv) {
+ if(uv2==p_vert.uv2) {
+ return (color<p_vert.color);
+ } else
+ return (uv2<p_vert.uv2);
} else
- return (uv2<p_vert.uv2);
+ return (uv<p_vert.uv);
} else
- return (uv<p_vert.uv);
+ return (normal<p_vert.normal);
} else
- return (normal<p_vert.normal);
+ return vertex<p_vert.vertex;
} else
- return vertex<p_vert.vertex;
+ return uid < p_vert.uid;
}
+
+ Vertex() { uid=0; idx=0; }
};
struct Node {
@@ -613,7 +619,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 319c1ad8b7..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>
}
@@ -997,8 +1000,8 @@ Error DocData::save(const String& p_path) {
_write_string(f,1,"</constants>");
- _write_string(f,1,"<theme_items>");
if (c.theme_properties.size()) {
+ _write_string(f,1,"<theme_items>");
for(int i=0;i<c.theme_properties.size();i++) {
@@ -1007,9 +1010,10 @@ Error DocData::save(const String& p_path) {
_write_string(f,2,"</theme_item>");
}
+ _write_string(f,1,"</theme_items>");
}
- _write_string(f,0,"</theme_items>");
+ _write_string(f,0,"</class>");
}
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 &quot;name&quot; arguemnt.
+ Add an animation resource to the player, which will be later referenced by the &quot;name&quot; 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/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 43c18341be..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();
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..eee4125e93 100644
--- a/tools/editor/editor_dir_dialog.cpp
+++ b/tools/editor/editor_dir_dialog.cpp
@@ -69,7 +69,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..2283a2df14 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);
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
index 6e8cb987e9..58f9afaa5d 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());
}
@@ -938,7 +946,7 @@ 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);
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 a137b6cd34..f859d19504 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -33,8 +33,6 @@
#include "editor_fonts.h"
#include "editor_help.h"
-#include "scene/io/scene_saver.h"
-#include "scene/io/scene_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/resource_loader.h"
#include "servers/physics_2d_server.h"
@@ -71,11 +69,13 @@
#include "plugins/item_list_editor_plugin.h"
#include "plugins/stream_editor_plugin.h"
#include "plugins/multimesh_editor_plugin.h"
+#include "plugins/mesh_editor_plugin.h"
#include "plugins/theme_editor_plugin.h"
#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"
@@ -141,7 +141,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
@@ -214,13 +214,13 @@ 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();
@@ -233,25 +233,6 @@ void EditorNode::_notification(int p_what) {
if (defer_load_scene!="") {
-#ifdef OLD_SCENE_FORMAT_ENABLED
-
- if (convert_old) {
- get_scene()->quit();
- Node *scn = SceneLoader::load(defer_load_scene,true);
- ERR_EXPLAIN("Couldn't load scene: "+defer_load_scene);
- ERR_FAIL_COND(!scn);
- Ref<PackedScene> sdata = memnew( PackedScene );
- Error err = sdata->pack(scn);
- ERR_EXPLAIN("Couldn't repack scene: "+defer_load_scene);
- ERR_FAIL_COND(err!=OK);
- err = ResourceSaver::save(defer_load_scene,sdata);
- ERR_EXPLAIN("Couldn't resave scene: "+defer_load_scene);
- ERR_FAIL_COND(err!=OK);
-
- return;
- }
-
-#endif
load_scene(defer_load_scene);
defer_load_scene="";
}
@@ -262,7 +243,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();
}
/*
@@ -886,65 +867,6 @@ void EditorNode::_dialog_action(String p_file) {
load_scene(p_file);
} break;
-#ifdef OLD_SCENE_FORMAT_ENABLED
- case FILE_OPEN_OLD_SCENE: {
-
- String lpath = Globals::get_singleton()->localize_path(p_file);
- if (!lpath.begins_with("res://")) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("Ugh");
- accept->set_text("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path.");
- accept->popup_centered(Size2(300,120));
- return ;
- }
-
- Node*new_scene=SceneLoader::load(lpath,true);
-
- if (!new_scene) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("Ugh");
- accept->set_text("Error loading scene.");
- accept->popup_centered(Size2(300,70));;
- return ;
- }
-
- Node *old_scene = edited_scene;
- _hide_top_editors();
- set_edited_scene(NULL);
- editor_data.clear_editor_states();
- if (old_scene) {
- memdelete(old_scene);
- }
-
- set_edited_scene(new_scene);
- scene_tree_dock->set_selected(new_scene);
- _get_scene_metadata();
-
- editor_data.get_undo_redo().clear_history();
- saved_version=editor_data.get_undo_redo().get_version();
- _update_title();
-
- _add_to_recent_scenes(lpath);
-
- if (new_scene->has_meta("__editor_plugin_screen__")) {
-
- String editor = new_scene->get_meta("__editor_plugin_screen__");
- for(int i=0;i<editor_table.size();i++) {
-
- if (editor_table[i]->get_name()==editor) {
- _editor_select(i);
- break;
- }
- }
- }
-
-
- } break;
-#endif
case FILE_SAVE_OPTIMIZED: {
@@ -1056,6 +978,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;
@@ -1311,7 +1242,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());
@@ -1389,6 +1320,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);
@@ -1467,13 +1400,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;
}
@@ -1679,28 +1609,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
open_request(previous_scenes.back()->get());
} break;
-#ifdef OLD_SCENE_FORMAT_ENABLED
- case FILE_OPEN_OLD_SCENE: {
-
- //print_tree();
- file->set_mode(FileDialog::MODE_OPEN_FILE);
- //not for now?
- file->clear_filters();
- file->add_filter("*.xml");
-
-
- //file->set_current_path(current_path);
- Node *scene = edited_scene;
- if (scene) {
- file->set_current_path(scene->get_filename());
- };
- file->set_title("Open Scene");
- file->popup_centered_ratio();
-
-
- } break;
-
-#endif
case FILE_SAVE_SCENE: {
@@ -1762,6 +1670,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;
@@ -2001,7 +1921,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: {
@@ -2124,6 +2044,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();;
@@ -2180,7 +2141,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;
@@ -2438,6 +2399,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_tree())
+ get_tree()->set_edited_scene_root(edited_scene);
if (edited_scene) {
if (p_scene->get_parent()!=scene_root)
@@ -2481,7 +2444,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;
}
@@ -2675,7 +2638,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;
}
@@ -2875,6 +2838,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);
}
@@ -3299,7 +3264,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);
@@ -3362,13 +3327,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);
@@ -3476,7 +3441,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);
@@ -3549,9 +3514,6 @@ EditorNode::EditorNode() {
p=import_menu->get_popup();
p->add_item("Sub-Scene",FILE_IMPORT_SUBSCENE);
-#ifdef OLD_SCENE_FORMAT_ENABLED
- p->add_item("Import Old Scene",FILE_OPEN_OLD_SCENE);
-#endif
p->add_separator();
p->connect("item_pressed",this,"_menu_option");
@@ -3731,8 +3693,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 );
@@ -3743,8 +3705,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 );
@@ -4052,8 +4014,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))));
@@ -4073,12 +4035,15 @@ 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) ) );
+ 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) ) );
add_editor_plugin( memnew( ThemeEditorPlugin(this) ) );
add_editor_plugin( memnew( MultiMeshEditorPlugin(this) ) );
+ add_editor_plugin( memnew( MeshInstanceEditorPlugin(this) ) );
add_editor_plugin( memnew( AnimationTreeEditorPlugin(this) ) );
add_editor_plugin( memnew( SamplePlayerEditorPlugin(this) ) );
add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) );
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 2cec301cf6..7560c2b149 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,
@@ -133,6 +135,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 +214,7 @@ class EditorNode : public Node {
AcceptDialog *load_error_dialog;
Control *scene_root_base;
+ Ref<Theme> theme;
PopupMenu *recent_scenes;
Button *property_back;
@@ -471,6 +475,9 @@ public:
void stop_child_process();
+ Ref<Theme> get_editor_theme() const { return theme; }
+
+
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 6f1a24d7e8..bc800d7e9e 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -30,7 +30,7 @@
#include "os/os.h"
#include "os/dir_access.h"
#include "os/file_access.h"
-#include "io/object_format_xml.h"
+
#include "version.h"
#include "scene/main/scene_main_loop.h"
#include "os/os.h"
@@ -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,7 @@ 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/idle_parse_delay",2);
set("text_editor/create_signal_callbacks",true);
@@ -416,6 +419,8 @@ void EditorSettings::_load_defaults() {
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);
@@ -438,8 +443,10 @@ void EditorSettings::_load_defaults() {
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 +469,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/editor_shape_gizmos.cpp b/tools/editor/editor_shape_gizmos.cpp
deleted file mode 100644
index df7332b64a..0000000000
--- a/tools/editor/editor_shape_gizmos.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/*************************************************************************/
-/* editor_shape_gizmos.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 "editor_shape_gizmos.h"
-
-
-
-
-
-
-String EditableShapeSpatialGizmo::get_handle_name(int p_idx) const {
-
- if (es->cast_to<EditableSphere>()) {
-
- return "Radius";
- }
-#if 0
- if (es->cast_to<EditableBox>()) {
-
- return "Extents";
- }
-
- if (es->cast_to<EditableCapsule>()) {
-
- return p_idx==0?"Radius":"Height";
- }
-
- if (es->cast_to<EditableRay>()) {
-
- return "Length";
- }
-#endif
- return "";
-}
-Variant EditableShapeSpatialGizmo::get_handle_value(int p_idx) const{
-
- if (es->cast_to<EditableSphere>()) {
-
- EditableSphere *ss = es->cast_to<EditableSphere>();
- return ss->get_radius();
- }
-#if 0
- if (es->cast_to<EditableBox>()) {
-
- EditableBox *bs = es->cast_to<EditableBox>();
- return bs->get_extents();
- }
-
- if (es->cast_to<EditableCapsule>()) {
-
- EditableCapsule *cs = es->cast_to<EditableCapsule>();
- return p_idx==0?es->get_radius():es->get_height();
- }
-
- if (es->cast_to<EditableRay>()) {
-
- EditableRay* cs = es->cast_to<EditableRay>();
- return es->get_length();
- }
-#endif
- return Variant();
-}
-void EditableShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Transform gt = es->get_global_transform();
- gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
-
- if (es->cast_to<EditableSphere>()) {
-
- EditableSphere *ss = es->cast_to<EditableSphere>();
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(4096,0,0),sg[0],sg[1],ra,rb);
- float d = ra.x;
- if (d<0.001)
- d=0.001;
-
- ss->set_radius(d);
- }
-
-#if 0
- if (es->cast_to<EditableRay>()) {
-
- EditableRay*cs = es->cast_to<EditableRay>();
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,4096),sg[0],sg[1],ra,rb);
- float d = ra.z;
- if (d<0.001)
- d=0.001;
-
- rs->set_length(d);
- }
-
-
- if (es->cast_to<EditableBox>()) {
-
- Vector3 axis;
- axis[p_idx]=1.0;
- EditableBox *bs = es->cast_to<EditableBox>();
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (d<0.001)
- d=0.001;
-
- Vector3 he = bs->get_extents();
- he[p_idx]=d;
- bs->set_extents(he);
-
- }
-
- if (es->cast_to<EditableCapsule>()) {
-
- Vector3 axis;
- axis[p_idx]=1.0;
- EditableCapsule *cs = es->cast_to<EditableCapsule>();
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (p_idx==1)
- d-=es->get_radius();
- if (d<0.001)
- d=0.001;
-
- if (p_idx==0)
- es->set_radius(d);
- else if (p_idx==1)
- es->set_height(d*2.0);
-
- }
-
-#endif
-
-}
-void EditableShapeSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
-
- if (es->cast_to<EditableSphere>()) {
-
- EditableSphere *ss = es->cast_to<EditableSphere>();
- if (p_cancel) {
- ss->set_radius(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Sphere Shape Radius");
- ur->add_do_method(ss,"set_radius",ss->get_radius());
- ur->add_undo_method(ss,"set_radius",p_restore);
- ur->commit_action();
-
- }
-#if 0
- if (es->cast_to<EditableBox>()) {
-
- EditableBox *ss = es->cast_to<EditableBox>();
- if (p_cancel) {
- ss->set_extents(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Box Shape Extents");
- ur->add_do_method(ss,"set_extents",ss->get_extents());
- ur->add_undo_method(ss,"set_extents",p_restore);
- ur->commit_action();
- }
-
- if (es->cast_to<EditableCapsule>()) {
-
- EditableCapsule *cs = es->cast_to<EditableCapsule>();
- if (p_cancel) {
- if (p_idx==0)
- ss->set_radius(p_restore);
- else
- ss->set_height(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- if (p_idx==0) {
- ur->create_action("Change Capsule Shape Radius");
- ur->add_do_method(ss,"set_radius",ss->get_radius());
- ur->add_undo_method(ss,"set_radius",p_restore);
- } else {
- ur->create_action("Change Capsule Shape Height");
- ur->add_do_method(ss,"set_height",ss->get_height());
- ur->add_undo_method(ss,"set_height",p_restore);
-
- }
-
- ur->commit_action();
-
- }
-
- if (es->cast_to<EditableRay>()) {
-
- EditableRay*rs = es->cast_to<EditableRay>()
- if (p_cancel) {
- ss->set_length(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Ray Shape Length");
- ur->add_do_method(ss,"set_length",ss->get_length());
- ur->add_undo_method(ss,"set_length",p_restore);
- ur->commit_action();
-
- }
-#endif
-}
-void EditableShapeSpatialGizmo::redraw(){
-
- clear();
-
- if (es->cast_to<EditableSphere>()) {
-
- EditableSphere* sp= es->cast_to<EditableSphere>();
- float r=sp->get_radius();
-
- Vector<Vector3> points;
-
- for(int i=0;i<=360;i++) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));
- points.push_back(Vector3(a.x,a.y,0));
- points.push_back(Vector3(b.x,b.y,0));
-
- }
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- collision_segments.push_back(Vector3(a.x,0,a.y));
- collision_segments.push_back(Vector3(b.x,0,b.y));
- collision_segments.push_back(Vector3(0,a.x,a.y));
- collision_segments.push_back(Vector3(0,b.x,b.y));
- collision_segments.push_back(Vector3(a.x,a.y,0));
- collision_segments.push_back(Vector3(b.x,b.y,0));
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(collision_segments);
- Vector<Vector3> handles;
- handles.push_back(Vector3(r,0,0));
- add_handles(handles);
-
- }
-
-#if 0
- if (es->cast_to<EditableBox>()) {
-
- EditableBox*bs = es->cast_to<EditableBox>();
- Vector<Vector3> lines;
- AABB aabb;
- aabb.pos=-bs->get_extents();
- aabb.size=aabb.pos*-2;
-
- for(int i=0;i<12;i++) {
- Vector3 a,b;
- aabb.get_edge(i,a,b);
- lines.push_back(a);
- lines.push_back(b);
- }
-
- Vector<Vector3> handles;
-
- for(int i=0;i<3;i++) {
-
- Vector3 ax;
- ax[i]=bs->get_extents()[i];
- handles.push_back(ax);
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(lines);
- add_handles(handles);
-
- }
-
- if (es->cast_to<EditableCapsule>()) {
-
- EditableCapsule *cs = es->cast_to<EditableCapsule>();
- float radius = es->get_radius();
- float height = es->get_height();
-
-
- Vector<Vector3> points;
-
- Vector3 d(0,height*0.5,0);
- for(int i=0;i<360;i++) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
-
- points.push_back(Vector3(a.x,0,a.y)+d);
- points.push_back(Vector3(b.x,0,b.y)+d);
-
- points.push_back(Vector3(a.x,0,a.y)-d);
- points.push_back(Vector3(b.x,0,b.y)-d);
-
- if (i%90==0) {
-
- points.push_back(Vector3(a.x,0,a.y)+d);
- points.push_back(Vector3(a.x,0,a.y)-d);
- }
-
- Vector3 dud = i<180?d:-d;
-
- points.push_back(Vector3(0,a.x,a.y)+dud);
- points.push_back(Vector3(0,b.x,b.y)+dud);
- points.push_back(Vector3(a.y,a.x,0)+dud);
- points.push_back(Vector3(b.y,b.x,0)+dud);
-
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
-
- collision_segments.push_back(Vector3(a.x,0,a.y)+d);
- collision_segments.push_back(Vector3(b.x,0,b.y)+d);
-
- collision_segments.push_back(Vector3(a.x,0,a.y)-d);
- collision_segments.push_back(Vector3(b.x,0,b.y)-d);
-
- if (i%16==0) {
-
- collision_segments.push_back(Vector3(a.x,0,a.y)+d);
- collision_segments.push_back(Vector3(a.x,0,a.y)-d);
- }
-
- Vector3 dud = i<32?d:-d;
-
- collision_segments.push_back(Vector3(0,a.x,a.y)+dud);
- collision_segments.push_back(Vector3(0,b.x,b.y)+dud);
- collision_segments.push_back(Vector3(a.y,a.x,0)+dud);
- collision_segments.push_back(Vector3(b.y,b.x,0)+dud);
-
- }
-
- add_collision_segments(collision_segments);
-
- Vector<Vector3> handles;
- handles.push_back(Vector3(es->get_radius(),0,0));
- handles.push_back(Vector3(0,es->get_height()*0.5+es->get_radius(),0));
- add_handles(handles);
-
-
- }
-
- if (es->cast_to<EditablePlane>()) {
-
- EditablePlane* ps=es->cast_to<EditablePlane();
- Plane p = ps->get_plane();
- Vector<Vector3> points;
-
- Vector3 n1 = p.get_any_perpendicular_normal();
- Vector3 n2 = p.normal.cross(n1).normalized();
-
- Vector3 pface[4]={
- p.normal*p.d+n1*10.0+n2*10.0,
- p.normal*p.d+n1*10.0+n2*-10.0,
- p.normal*p.d+n1*-10.0+n2*-10.0,
- p.normal*p.d+n1*-10.0+n2*10.0,
- };
-
- points.push_back(pface[0]);
- points.push_back(pface[1]);
- points.push_back(pface[1]);
- points.push_back(pface[2]);
- points.push_back(pface[2]);
- points.push_back(pface[3]);
- points.push_back(pface[3]);
- points.push_back(pface[0]);
- points.push_back(p.normal*p.d);
- points.push_back(p.normal*p.d+p.normal*3);
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
-
- }
-
-
- if (es->cast_to<EditableRay>()) {
-
- EditableRay*cs = es->cast_to<EditableRay>();
-
- Vector<Vector3> points;
- points.push_back(Vector3());
- points.push_back(Vector3(0,0,rs->get_length()));
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
- Vector<Vector3> handles;
- handles.push_back(Vector3(0,0,rs->get_length()));
- add_handles(handles);
-
-
- }
-
-#endif
-
-}
-EditableShapeSpatialGizmo::EditableShapeSpatialGizmo(EditableShape* p_cs) {
-
- es=p_cs;
- set_spatial_node(p_cs);
-}
-
-
-
-EditorShapeGizmos::EditorShapeGizmos()
-{
-}
diff --git a/tools/editor/editor_shape_gizmos.h b/tools/editor/editor_shape_gizmos.h
deleted file mode 100644
index 4b5af49b4e..0000000000
--- a/tools/editor/editor_shape_gizmos.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*************************************************************************/
-/* editor_shape_gizmos.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 EDITOR_SHAPE_GIZMOS_H
-#define EDITOR_SHAPE_GIZMOS_H
-
-#include "spatial_editor_gizmos.h"
-#include "scene/3d/editable_shape.h"
-
-
-class EditableShapeSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(EditableShapeSpatialGizmo,SpatialGizmoTool);
-
- EditableShape *es;
-
-public:
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
- void redraw();
- EditableShapeSpatialGizmo(EditableShape* p_cs=NULL);
-
-};
-
-
-
-class EditorShapeGizmos
-{
-public:
- EditorShapeGizmos();
-};
-
-#endif // EDITOR_SHAPE_GIZMOS_H
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_baked_light.png b/tools/editor/icons/icon_baked_light.png
new file mode 100644
index 0000000000..48039e264c
--- /dev/null
+++ b/tools/editor/icons/icon_baked_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_baked_light_instance.png b/tools/editor/icons/icon_baked_light_instance.png
new file mode 100644
index 0000000000..77e53aa8f6
--- /dev/null
+++ b/tools/editor/icons/icon_baked_light_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_item_shader.png b/tools/editor/icons/icon_canvas_item_shader.png
new file mode 100644
index 0000000000..a5f4e7bf85
--- /dev/null
+++ b/tools/editor/icons/icon_canvas_item_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_item_shader_graph.png b/tools/editor/icons/icon_canvas_item_shader_graph.png
new file mode 100644
index 0000000000..bba966b43e
--- /dev/null
+++ b/tools/editor/icons/icon_canvas_item_shader_graph.png
Binary files differ
diff --git a/tools/editor/icons/icon_collision_polygon.png b/tools/editor/icons/icon_collision_polygon.png
new file mode 100644
index 0000000000..a82b43589e
--- /dev/null
+++ b/tools/editor/icons/icon_collision_polygon.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_comment.png b/tools/editor/icons/icon_graph_comment.png
new file mode 100644
index 0000000000..bf7889c510
--- /dev/null
+++ b/tools/editor/icons/icon_graph_comment.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_cube_uniform.png b/tools/editor/icons/icon_graph_cube_uniform.png
new file mode 100644
index 0000000000..d1b92b4943
--- /dev/null
+++ b/tools/editor/icons/icon_graph_cube_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_input.png b/tools/editor/icons/icon_graph_input.png
new file mode 100644
index 0000000000..a396bc2350
--- /dev/null
+++ b/tools/editor/icons/icon_graph_input.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_rgb.png b/tools/editor/icons/icon_graph_rgb.png
new file mode 100644
index 0000000000..abffaedd34
--- /dev/null
+++ b/tools/editor/icons/icon_graph_rgb.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_rgb_op.png b/tools/editor/icons/icon_graph_rgb_op.png
new file mode 100644
index 0000000000..642fc838c2
--- /dev/null
+++ b/tools/editor/icons/icon_graph_rgb_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_rgb_uniform.png b/tools/editor/icons/icon_graph_rgb_uniform.png
new file mode 100644
index 0000000000..92c79997ef
--- /dev/null
+++ b/tools/editor/icons/icon_graph_rgb_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar.png b/tools/editor/icons/icon_graph_scalar.png
new file mode 100644
index 0000000000..028d0e9ea4
--- /dev/null
+++ b/tools/editor/icons/icon_graph_scalar.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar_interp.png b/tools/editor/icons/icon_graph_scalar_interp.png
new file mode 100644
index 0000000000..4f178a27c4
--- /dev/null
+++ b/tools/editor/icons/icon_graph_scalar_interp.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar_op.png b/tools/editor/icons/icon_graph_scalar_op.png
new file mode 100644
index 0000000000..0fc4cae94c
--- /dev/null
+++ b/tools/editor/icons/icon_graph_scalar_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar_uniform.png b/tools/editor/icons/icon_graph_scalar_uniform.png
new file mode 100644
index 0000000000..fc6590a8cf
--- /dev/null
+++ b/tools/editor/icons/icon_graph_scalar_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalars_to_vec.png b/tools/editor/icons/icon_graph_scalars_to_vec.png
new file mode 100644
index 0000000000..7ca39a2f56
--- /dev/null
+++ b/tools/editor/icons/icon_graph_scalars_to_vec.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_texscreen.png b/tools/editor/icons/icon_graph_texscreen.png
new file mode 100644
index 0000000000..e183a8fa56
--- /dev/null
+++ b/tools/editor/icons/icon_graph_texscreen.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_texture_uniform.png b/tools/editor/icons/icon_graph_texture_uniform.png
new file mode 100644
index 0000000000..7517ac1d92
--- /dev/null
+++ b/tools/editor/icons/icon_graph_texture_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_time.png b/tools/editor/icons/icon_graph_time.png
new file mode 100644
index 0000000000..b61e45589f
--- /dev/null
+++ b/tools/editor/icons/icon_graph_time.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_dp.png b/tools/editor/icons/icon_graph_vec_dp.png
new file mode 100644
index 0000000000..059c3025e7
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vec_dp.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_interp.png b/tools/editor/icons/icon_graph_vec_interp.png
new file mode 100644
index 0000000000..daf7a00203
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vec_interp.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_length.png b/tools/editor/icons/icon_graph_vec_length.png
new file mode 100644
index 0000000000..60ade8c90a
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vec_length.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_op.png b/tools/editor/icons/icon_graph_vec_op.png
new file mode 100644
index 0000000000..f2a7a51123
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vec_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_scalar_op.png b/tools/editor/icons/icon_graph_vec_scalar_op.png
new file mode 100644
index 0000000000..f0f4e7a196
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vec_scalar_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_to_scalars.png b/tools/editor/icons/icon_graph_vec_to_scalars.png
new file mode 100644
index 0000000000..a677a7cc53
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vec_to_scalars.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vecs_to_xform.png b/tools/editor/icons/icon_graph_vecs_to_xform.png
new file mode 100644
index 0000000000..51216c93eb
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vecs_to_xform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vector.png b/tools/editor/icons/icon_graph_vector.png
new file mode 100644
index 0000000000..9dfe47d757
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vector.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vector_uniform.png b/tools/editor/icons/icon_graph_vector_uniform.png
new file mode 100644
index 0000000000..611539fca7
--- /dev/null
+++ b/tools/editor/icons/icon_graph_vector_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform.png b/tools/editor/icons/icon_graph_xform.png
new file mode 100644
index 0000000000..22df472be4
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_mult.png b/tools/editor/icons/icon_graph_xform_mult.png
new file mode 100644
index 0000000000..5d0ce7982d
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform_mult.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_scalar_func.png b/tools/editor/icons/icon_graph_xform_scalar_func.png
new file mode 100644
index 0000000000..e53f08a564
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform_scalar_func.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_to_vecs.png b/tools/editor/icons/icon_graph_xform_to_vecs.png
new file mode 100644
index 0000000000..847261f726
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform_to_vecs.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_uniform.png b/tools/editor/icons/icon_graph_xform_uniform.png
new file mode 100644
index 0000000000..94c9759b25
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_vec_func.png b/tools/editor/icons/icon_graph_xform_vec_func.png
new file mode 100644
index 0000000000..f3ba528896
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform_vec_func.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_vec_imult.png b/tools/editor/icons/icon_graph_xform_vec_imult.png
new file mode 100644
index 0000000000..7e7330cb8c
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform_vec_imult.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_vec_mult.png b/tools/editor/icons/icon_graph_xform_vec_mult.png
new file mode 100644
index 0000000000..f80a28c80d
--- /dev/null
+++ b/tools/editor/icons/icon_graph_xform_vec_mult.png
Binary files differ
diff --git a/tools/editor/icons/icon_immediate_geometry.png b/tools/editor/icons/icon_immediate_geometry.png
new file mode 100644
index 0000000000..e7fa8a9e42
--- /dev/null
+++ b/tools/editor/icons/icon_immediate_geometry.png
Binary files differ
diff --git a/tools/editor/icons/icon_kinematic_body.png b/tools/editor/icons/icon_kinematic_body.png
new file mode 100644
index 0000000000..7feb38f6ba
--- /dev/null
+++ b/tools/editor/icons/icon_kinematic_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_kinematic_body_2d.png b/tools/editor/icons/icon_kinematic_body_2d.png
new file mode 100644
index 0000000000..3d8e09a179
--- /dev/null
+++ b/tools/editor/icons/icon_kinematic_body_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_shader.png b/tools/editor/icons/icon_material_shader.png
new file mode 100644
index 0000000000..0e476b2540
--- /dev/null
+++ b/tools/editor/icons/icon_material_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_shader_graph.png b/tools/editor/icons/icon_material_shader_graph.png
new file mode 100644
index 0000000000..68d8b4cb49
--- /dev/null
+++ b/tools/editor/icons/icon_material_shader_graph.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation.png b/tools/editor/icons/icon_navigation.png
new file mode 100644
index 0000000000..eeaa660f8d
--- /dev/null
+++ b/tools/editor/icons/icon_navigation.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation_mesh_instance.png b/tools/editor/icons/icon_navigation_mesh_instance.png
new file mode 100644
index 0000000000..163bd0cdb3
--- /dev/null
+++ b/tools/editor/icons/icon_navigation_mesh_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_2_alt.png b/tools/editor/icons/icon_panels_2_alt.png
new file mode 100644
index 0000000000..2006f212ce
--- /dev/null
+++ b/tools/editor/icons/icon_panels_2_alt.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_3_alt.png b/tools/editor/icons/icon_panels_3_alt.png
new file mode 100644
index 0000000000..5195b799a5
--- /dev/null
+++ b/tools/editor/icons/icon_panels_3_alt.png
Binary files differ
diff --git a/tools/editor/icons/icon_particle_attractor_2d.png b/tools/editor/icons/icon_particle_attractor_2d.png
new file mode 100644
index 0000000000..bb66611e45
--- /dev/null
+++ b/tools/editor/icons/icon_particle_attractor_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_pin_joint.png b/tools/editor/icons/icon_pin_joint.png
new file mode 100644
index 0000000000..cdfae660d8
--- /dev/null
+++ b/tools/editor/icons/icon_pin_joint.png
Binary files differ
diff --git a/tools/editor/icons/icon_polygon_2d.png b/tools/editor/icons/icon_polygon_2d.png
new file mode 100644
index 0000000000..9deb63a248
--- /dev/null
+++ b/tools/editor/icons/icon_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_ray_cast.png b/tools/editor/icons/icon_ray_cast.png
new file mode 100644
index 0000000000..a53ef0b516
--- /dev/null
+++ b/tools/editor/icons/icon_ray_cast.png
Binary files differ
diff --git a/tools/editor/icons/icon_slider_joint.png b/tools/editor/icons/icon_slider_joint.png
new file mode 100644
index 0000000000..ce35b6bfa2
--- /dev/null
+++ b/tools/editor/icons/icon_slider_joint.png
Binary files differ
diff --git a/tools/editor/icons/icon_touch_screen_button.png b/tools/editor/icons/icon_touch_screen_button.png
new file mode 100644
index 0000000000..16e84927f1
--- /dev/null
+++ b/tools/editor/icons/icon_touch_screen_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_vehicle_body.png b/tools/editor/icons/icon_vehicle_body.png
new file mode 100644
index 0000000000..1c6af388eb
--- /dev/null
+++ b/tools/editor/icons/icon_vehicle_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_vehicle_wheel.png b/tools/editor/icons/icon_vehicle_wheel.png
new file mode 100644
index 0000000000..161283e1bf
--- /dev/null
+++ b/tools/editor/icons/icon_vehicle_wheel.png
Binary files differ
diff --git a/tools/editor/icons/icon_y_sort.png b/tools/editor/icons/icon_y_sort.png
new file mode 100644
index 0000000000..6f80fac156
--- /dev/null
+++ b/tools/editor/icons/icon_y_sort.png
Binary files differ
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 6ba5dc01f6..1fd7d26f8b 100644
--- a/tools/editor/io_plugins/editor_font_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp
@@ -92,6 +92,7 @@ public:
String gradient_image;
+ bool disable_filter;
bool round_advance;
@@ -153,6 +154,8 @@ public:
color_use_monochrome=p_value;
else if (n=="advanced/round_advance")
round_advance=p_value;
+ else if (n=="advanced/disable_filter")
+ disable_filter=p_value;
else
return false;
@@ -217,6 +220,8 @@ public:
r_ret=color_use_monochrome;
else if (n=="advanced/round_advance")
r_ret=round_advance;
+ else if (n=="advanced/disable_filter")
+ r_ret=disable_filter;
else
return false;
@@ -265,6 +270,7 @@ public:
}
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"));
}
@@ -302,6 +308,7 @@ public:
color_use_monochrome=false;
round_advance=true;
+ disable_filter=false;
}
@@ -331,6 +338,7 @@ public:
color_use_monochrome=false;
round_advance=true;
+ disable_filter=false;
}
@@ -521,7 +529,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();
}
@@ -1260,6 +1268,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
int space_space = from->get_option("extra_space/space");
int top_space = from->get_option("extra_space/top");
int bottom_space = from->get_option("extra_space/bottom");
+ bool disable_filter = from->get_option("advanced/disable_filter");
Ref<Font> font;
@@ -1279,7 +1288,12 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
//register texures
{
Ref<ImageTexture> t = memnew(ImageTexture);
- t->create_from_image(atlas);
+ int flags;
+ if (disable_filter)
+ flags=0;
+ else
+ flags=Texture::FLAG_FILTER;
+ t->create_from_image(atlas,flags);
t->set_storage( ImageTexture::STORAGE_COMPRESS_LOSSLESS );
font->add_texture(t);
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index 9bee47ca66..529ed3374b 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -61,6 +61,8 @@ struct ColladaImport {
Color ambient;
bool found_directional;
bool force_make_tangents;
+ bool apply_mesh_xform_to_vertices;
+ float bake_fps;
@@ -68,6 +70,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 +79,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 +99,8 @@ struct ColladaImport {
found_ambient=false;
found_directional=false;
force_make_tangents=false;
+ apply_mesh_xform_to_vertices=true;
+ bake_fps=15;
}
};
@@ -108,7 +114,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 +174,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;
@@ -295,15 +329,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;
@@ -694,6 +721,7 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co
// Must convert to GL/DX format.
int _prim_ofs=0;
+ int vertidx=0;
for(int p_i=0;p_i<p.count;p_i++) {
@@ -718,6 +746,8 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co
ERR_FAIL_INDEX_V(src,p.indices.size(),ERR_INVALID_DATA);
Collada::Vertex vertex;
+ if (p_morph_data)
+ vertex.uid=vertidx++;
int vertex_index=p.indices[src+vertex_ofs]; //used for index field (later used by controllers)
int vertex_pos = (vertex_src->stride?vertex_src->stride:3) * vertex_index;
@@ -746,7 +776,7 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co
Vector3 tangent =Vector3(tangent_src->array[tangent_pos+0],tangent_src->array[tangent_pos+1],tangent_src->array[tangent_pos+2]);
vertex.tangent.normal=tangent;
- vertex.tangent.d= vertex.normal.cross(tangent).dot(binormal) > 0 ? -1 : 1;
+ vertex.tangent.d= vertex.normal.cross(tangent).dot(binormal) > 0 ? 1 : -1;
}
}
@@ -781,6 +811,8 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co
vertex.vertex.z = -vertex.vertex.z;
SWAP( vertex.normal.z, vertex.normal.y );
vertex.normal.z = -vertex.normal.z;
+ SWAP( vertex.tangent.normal.z, vertex.tangent.normal.y );
+ vertex.tangent.normal.z = -vertex.tangent.normal.z;
}
@@ -1495,6 +1527,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>();
@@ -1511,8 +1546,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;
@@ -1608,6 +1647,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);
@@ -1670,16 +1719,21 @@ void ColladaImport::_fix_param_animation_tracks() {
source=skin.base;
} else if (collada.state.morph_controller_data_map.has(source)) {
+
const Collada::MorphControllerData& morph = collada.state.morph_controller_data_map[source];
+
if (morph.targets.has("MORPH_WEIGHT") && morph.targets.has("MORPH_TARGET")) {
+
String weights = morph.targets["MORPH_WEIGHT"];
String targets = morph.targets["MORPH_TARGET"];
+ //fails here
if (morph.sources.has(targets) && morph.sources.has(weights)) {
const Collada::MorphControllerData::Source &weight_src=morph.sources[weights];
const Collada::MorphControllerData::Source &target_src=morph.sources[targets];
+
ERR_FAIL_COND(weight_src.array.size() != target_src.sarray.size());
for(int i=0;i<weight_src.array.size();i++) {
@@ -1688,6 +1742,7 @@ void ColladaImport::_fix_param_animation_tracks() {
String mesh_name = target_src.sarray[i];
if (collada.state.mesh_name_map.has(mesh_name) && collada.state.referenced_tracks.has(track_name)) {
+
const Vector<int>&rt = collada.state.referenced_tracks[track_name];
for(int rti=0;rti<rt.size();rti++) {
@@ -1718,7 +1773,7 @@ void ColladaImport::_fix_param_animation_tracks() {
void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) {
- print_line("-=-=-=-=-PRE CA");
+
_fix_param_animation_tracks();
for(int i=0;i<collada.state.animation_clips.size();i++) {
@@ -1731,6 +1786,7 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) {
for(int i=0;i<collada.state.animation_tracks.size();i++) {
Collada::AnimationTrack &at = collada.state.animation_tracks[i];
+ //print_line("CHANNEL: "+at.target+" PARAM: "+at.param);
if (!node_map.has(at.target)) {
print_line("Coudlnt find node: "+at.target);
continue;
@@ -1749,7 +1805,7 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones) {
}
create_animation(-1,p_make_tracks_in_all_bones);
- print_line("clipcount: "+itos(collada.state.animation_clips.size()));
+ //print_line("clipcount: "+itos(collada.state.animation_clips.size()));
for(int i=0;i<collada.state.animation_clips.size();i++)
create_animation(i,p_make_tracks_in_all_bones);
@@ -1761,10 +1817,10 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
if (p_clip==-1) {
- print_line("default");
+ //print_line("default");
animation->set_name("default");
} else {
- print_line("clip name: "+collada.state.animation_clips[p_clip].name);
+ //print_line("clip name: "+collada.state.animation_clips[p_clip].name);
animation->set_name(collada.state.animation_clips[p_clip].name);
}
@@ -1823,20 +1879,23 @@ 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<collada.state.animation_length) {
- if (f>=collada.state.animation_length)
- f=collada.state.animation_length;
+ while(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));
+
+ //print_line("anim len: "+rtos(anim_length));
animation->set_length(anim_length);
bool tracks_found=false;
@@ -1861,7 +1920,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
Collada::Node *cn = collada.state.scene_map[E->get()];
if (cn->ignore_anim) {
- print_line("warning, ignoring animation on node: "+path);
+ //print_line("warning, ignoring animation on node: "+path);
continue;
}
@@ -1880,6 +1939,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");
+
}
@@ -2130,14 +2191,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);
@@ -2162,7 +2223,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;
@@ -2171,8 +2232,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")) {
@@ -2201,7 +2260,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);
@@ -2218,8 +2277,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 2482728c87..06780e4d8a 100644
--- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
@@ -40,6 +40,7 @@
#include "scene/3d/body_shape.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/portal.h"
+#include "scene/3d/vehicle_body.h"
#include "os/os.h"
@@ -77,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);
@@ -92,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();
@@ -140,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);
@@ -177,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
};
@@ -222,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"));
@@ -233,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;
@@ -262,15 +461,134 @@ 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 {
- add_margin_child("Animation Options",flags,true);
+ 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);
+}
+void EditorImportAnimationOptions::set_filter(const String& p_filter) {
+
+ filters->set_text(p_filter);
+}
+
+String EditorImportAnimationOptions::get_filter() const {
+
+ return filters->get_text();
+}
+
@@ -307,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);
}
@@ -412,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;
@@ -525,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())
@@ -543,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)));
@@ -555,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;
@@ -618,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);
@@ -641,6 +995,7 @@ const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_name
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,"Materials","Set Alpha in Materials (-alpha)",true},
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,"Materials","Set Vert. Color in Materials (-vcol)",true},
{EditorSceneImportPlugin::SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES,"Actions","SRGB->Linear Of Diffuse Textures",false},
+ {EditorSceneImportPlugin::SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY,"Actions","Convert Normal Maps to XY",true},
{EditorSceneImportPlugin::SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS,"Actions","Set Material Lightmap to UV2 if Tex2Array Exists",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,"Create","Create Collisions (-col},-colonly)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,"Create","Create Portals (-portal)",true},
@@ -649,9 +1004,10 @@ const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_name
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_BILLBOARDS,"Create","Create Billboards (-bb)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,"Create","Create Impostors (-imp:dist)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_LODS,"Create","Create LODs (-lod:dist)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Cars (-car)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Car Wheels (-wheel)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Vehicles (-vehicle)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Vehicle Wheels (-wheel)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_NAVMESH,"Create","Create Navigation Meshes (-navmesh)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_DETECT_LIGHTMAP_LAYER,"Create","Detect LightMap Layer (-lm:<int>).",true},
{-1,NULL,NULL,false}
};
@@ -789,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://");
@@ -811,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 );
@@ -896,7 +1266,7 @@ static String _fixstr(const String& p_what,const String& p_str) {
-void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<ImageTexture>, bool> &image_map) {
+void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<ImageTexture>, TextureRole> &image_map,int p_flags) {
switch(p_var.get_type()) {
@@ -908,7 +1278,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag
if (res->is_type("Texture") && !image_map.has(res)) {
- image_map.insert(res,false);
+ image_map.insert(res,TEXTURE_ROLE_DEFAULT);
} else {
@@ -924,11 +1294,22 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag
Ref<ImageTexture> tex =res->get(E->get().name);
if (tex.is_valid()) {
- image_map.insert(tex,true);
+ image_map.insert(tex,TEXTURE_ROLE_DIFFUSE);
}
+ } else if (E->get().type==Variant::OBJECT && res->cast_to<FixedMaterial>() && (E->get().name=="textures/normal")) {
+
+ Ref<ImageTexture> tex =res->get(E->get().name);
+ if (tex.is_valid()) {
+
+ image_map.insert(tex,TEXTURE_ROLE_NORMALMAP);
+ if (p_flags&SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY)
+ res->cast_to<FixedMaterial>()->set_fixed_flag(FixedMaterial::FLAG_USE_XY_NORMALMAP,true);
+ }
+
+
} else {
- _find_resources(res->get(E->get().name),image_map);
+ _find_resources(res->get(E->get().name),image_map,p_flags);
}
}
}
@@ -947,8 +1328,8 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
- _find_resources(E->get(),image_map);
- _find_resources(d[E->get()],image_map);
+ _find_resources(E->get(),image_map,p_flags);
+ _find_resources(d[E->get()],image_map,p_flags);
}
@@ -959,7 +1340,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag
Array a = p_var;
for(int i=0;i<a.size();i++) {
- _find_resources(a[i],image_map);
+ _find_resources(a[i],image_map,p_flags);
}
} break;
@@ -969,7 +1350,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag
}
-Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,bool >& image_map) {
+Node* EditorSceneImportPlugin::_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) {
// children first..
for(int i=0;i<p_node->get_child_count();i++) {
@@ -1000,7 +1381,7 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) {
- _find_resources(p_node->get(E->get().name),image_map);
+ _find_resources(p_node->get(E->get().name),image_map,p_flags);
}
}
@@ -1199,6 +1580,17 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
}
}
}
+
+
+ if (p_flags&SCENE_FLAG_DETECT_LIGHTMAP_LAYER && _teststr(name,"lm") && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ String str=name;
+ int layer = str.substr(str.find("lm")+3,str.length()).to_int();
+ mi->set_baked_light_texture_id(layer);
+ }
+
if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) {
if (isroot)
@@ -1262,6 +1654,46 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
p_node->replace_by(nmi);
memdelete(p_node);
p_node=nmi;
+ } else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"vehicle")) {
+
+ if (isroot)
+ return p_node;
+
+ Node *owner = p_node->get_owner();
+ Spatial *s = p_node->cast_to<Spatial>();
+ VehicleBody *bv = memnew( VehicleBody );
+ String n = _fixstr(p_node->get_name(),"vehicle");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform());
+
+ p_node=bv;
+
+
+ } else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"wheel")) {
+
+ if (isroot)
+ return p_node;
+
+ Node *owner = p_node->get_owner();
+ Spatial *s = p_node->cast_to<Spatial>();
+ VehicleWheel *bv = memnew( VehicleWheel );
+ String n = _fixstr(p_node->get_name(),"wheel");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform());
+
+ p_node=bv;
} else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) {
@@ -1750,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
@@ -1817,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)
@@ -1837,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;
}
@@ -1848,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());
@@ -1872,9 +2667,16 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
Ref<ResourceImportMetadata> imd = memnew(ResourceImportMetadata);
- Map< Ref<ImageTexture>,bool > imagemap;
+ 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
@@ -1918,7 +2720,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
int image_flags = from->get_option("texture_flags");
float image_quality = from->get_option("texture_quality");
- for (Map< Ref<ImageTexture>,bool >::Element *E=imagemap.front();E;E=E->next()) {
+ for (Map< Ref<ImageTexture>,TextureRole >::Element *E=imagemap.front();E;E=E->next()) {
//texture could be converted to something more useful for 3D, that could load individual mipmaps and stuff
//but not yet..
@@ -1954,6 +2756,11 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
print_line("flags: "+itos(image_flags));
uint32_t flags = image_flags;
+ if (E->get()==TEXTURE_ROLE_DIFFUSE && scene_flags&SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES)
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR;
+
+ if (E->get()==TEXTURE_ROLE_NORMALMAP && scene_flags&SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY)
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_NORMAL_TO_XY;
imd->set_option("flags",flags);
imd->set_option("format",image_format);
@@ -1993,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);
@@ -2012,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 3b39f0c962..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;
@@ -100,12 +100,26 @@ class EditorSceneImportPlugin : public EditorImportPlugin {
Vector<Ref<EditorSceneImporter> > importers;
- void _find_resources(const Variant& p_var,Map<Ref<ImageTexture>,bool >& image_map);
- Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,bool >& image_map);
+ enum TextureRole {
+ TEXTURE_ROLE_DEFAULT,
+ TEXTURE_ROLE_DIFFUSE,
+ TEXTURE_ROLE_NORMALMAP
+ };
+
+ 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);
@@ -125,6 +139,7 @@ public:
SCENE_FLAG_DETECT_ALPHA=1<<15,
SCENE_FLAG_DETECT_VCOLOR=1<<16,
SCENE_FLAG_CREATE_NAVMESH=1<<17,
+ SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
SCENE_FLAG_REMOVE_NOIMP=1<<24,
SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,
@@ -132,6 +147,14 @@ public:
SCENE_FLAG_GENERATE_TANGENT_ARRAYS=1<<27,
SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES=1<<28,
SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS=1<<29,
+ 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,
};
@@ -163,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;
@@ -177,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 760651bbfd..ce376f2e7b 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
@@ -46,6 +46,8 @@ static const char *flag_names[]={
"Filter (Magnifying)",
"Premultiply Alpha",
"Convert SRGB->Linear",
+ "Convert NormalMap to XY",
+ "Use Anisotropy",
NULL
};
@@ -59,6 +61,8 @@ static const char *flag_short_names[]={
"Filter",
"PMAlpha",
"ToLinear",
+ "ToRG",
+ "Anisoropic",
NULL
};
@@ -147,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");
@@ -407,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"));
@@ -425,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;
@@ -725,7 +733,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
bool atlas = from->get_option("atlas");
int flags=from->get_option("flags");
- print_line("GET FLAGS: "+itos(flags));
+
uint32_t tex_flags=0;
if (flags&EditorTextureImportPlugin::IMAGE_FLAG_REPEAT)
@@ -734,6 +742,10 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
tex_flags|=Texture::FLAG_FILTER;
if (!(flags&EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS))
tex_flags|=Texture::FLAG_MIPMAPS;
+ if (flags&EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR)
+ tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR;
+ if (flags&EditorTextureImportPlugin::IMAGE_FLAG_USE_ANISOTROPY)
+ tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER;
print_line("path: "+p_path+" flags: "+itos(tex_flags));
int shrink=1;
@@ -930,11 +942,15 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
image.premultiply_alpha();
}
- if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
-
- image.srgb_to_linear();
+ if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
+ image.normalmap_to_xy();
}
+ //if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+
+ // image.srgb_to_linear();
+ //}
+
if (shrink>1) {
int orig_w=image.get_width();
@@ -992,12 +1008,16 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
image.premultiply_alpha();
}
- if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
-
- print_line("CONVERT BECAUSE: "+itos(flags));
- image.srgb_to_linear();
+ if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
+ image.normalmap_to_xy();
}
+ //if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+//
+ // print_line("CONVERT BECAUSE: "+itos(flags));
+ // image.srgb_to_linear();
+ //}
+
int orig_w=image.get_width();
int orig_h=image.get_height();
@@ -1021,7 +1041,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
texture->create_from_image(image,tex_flags);
- if (shrink>1) {
+ if (shrink>1 || (format!=IMAGE_FORMAT_UNCOMPRESSED && (image.get_width()!=orig_w || image.get_height()!=orig_h))) {
texture->set_size_override(Size2(orig_w,orig_h));
}
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h
index 9374c6eb0b..e733a3ddf9 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.h
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.h
@@ -93,9 +93,12 @@ public:
IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
IMAGE_FLAG_FILTER=64, //almost always enabled
IMAGE_FLAG_PREMULT_ALPHA=128,//almost always enabled
- IMAGE_FLAG_CONVERT_TO_LINEAR=256 //convert image to linear
+ IMAGE_FLAG_CONVERT_TO_LINEAR=256, //convert image to linear
+ IMAGE_FLAG_CONVERT_NORMAL_TO_XY=512, //convert image to linear
+ 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 dea83e0ff8..42a185b7c2 100644
--- a/tools/editor/plugins/baked_light_baker.cpp
+++ b/tools/editor/plugins/baked_light_baker.cpp
@@ -4,6 +4,53 @@
#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));
+
+ if (lat==0) {
+ return 60;
+ } else if (lat==6) {
+ return 61;
+ }
+
+ int lon = Math::fast_ftoi(Math::floor( (Math_PI+Math::atan2(p_vector.x,p_vector.z))*12.0/(Math_PI*2.0) + 0.5))%12;
+
+ return lon+(lat-1)*12;
+}
+
+
+
+_FORCE_INLINE_ static Vector3 get_bit_normal(int p_bit) {
+
+ if (p_bit==61) {
+ return Vector3(0,1,0);
+ } else if (p_bit==62){
+ return Vector3(0,-1,0);
+ }
+
+ float latang = ((p_bit / 12)+1)*Math_PI/6.0;
+
+ Vector2 latv(Math::sin(latang),Math::cos(latang));
+
+ float lonang = ((p_bit%12)*Math_PI*2.0/12.0)-Math_PI;
+
+ Vector2 lonv(Math::sin(lonang),Math::cos(lonang));
+
+ return Vector3(lonv.x*latv.x,latv.y,lonv.y*latv.x).normalized();
+
+}
BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>& p_tex) {
@@ -28,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;
@@ -67,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 {
@@ -232,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();
@@ -434,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) {
@@ -525,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;
@@ -533,10 +605,12 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de
child->offset[2]=child->aabb.pos.z+child->aabb.size.z*0.5;
child->next_leaf=leaf_list;
+
for(int ci=0;ci<8;ci++) {
child->normal_accum[ci][0]=0;
child->normal_accum[ci][1]=0;
child->normal_accum[ci][2]=0;
+
}
child->bake_neighbour=0;
@@ -545,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];
@@ -593,11 +663,26 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de
pos.y=floor((pos.y+cell_size*0.5)/cell_size);
pos.z=floor((pos.z+cell_size*0.5)/cell_size);
- Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
- if (!E) {
- endpoint_normal[pos]=n;
- } else {
- E->get()+=n;
+ {
+ Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
+ if (!E) {
+ endpoint_normal[pos]=n;
+ } else {
+ E->get()+=n;
+ }
+ }
+
+ {
+
+ uint64_t bit = get_uv_normal_bit(n);
+
+ Map<Vector3,uint64_t>::Element *E=endpoint_normal_bits.find(pos);
+ if (!E) {
+ endpoint_normal_bits[pos]=(1<<bit);
+ } else {
+ E->get()|=(1<<bit);
+ }
+
}
}
@@ -677,18 +762,58 @@ void BakedLightBaker::_make_octree() {
pos.y=floor((pos.y+cell_size*0.5)/cell_size);
pos.z=floor((pos.z+cell_size*0.5)/cell_size);
- Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
- if (!E) {
- //?
- print_line("lolwut?");
- } else {
- Vector3 n = E->get().normalized();
- oct->normal_accum[ci][0]=n.x;
- oct->normal_accum[ci][1]=n.y;
- oct->normal_accum[ci][2]=n.z;
+ {
+ Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
+ if (!E) {
+ //?
+ print_line("lolwut?");
+ } else {
+ Vector3 n = E->get().normalized();
+ oct->normal_accum[ci][0]=n.x;
+ oct->normal_accum[ci][1]=n.y;
+ oct->normal_accum[ci][2]=n.z;
+ }
+
+ }
+
+ {
+
+ Map<Vector3,uint64_t>::Element *E=endpoint_normal_bits.find(pos);
+ if (!E) {
+ //?
+ print_line("lolwut?");
+ } else {
+
+ float max_aper=0;
+ for(uint64_t i=0;i<62;i++) {
+
+ if (!(E->get()&(1<<i)))
+ continue;
+ Vector3 ang_i = get_bit_normal(i);
+
+ for(uint64_t j=0;j<62;j++) {
+
+ if (i==j)
+ continue;
+ if (!(E->get()&(1<<j)))
+ continue;
+ Vector3 ang_j = get_bit_normal(j);
+ float ang = Math::acos(ang_i.dot(ang_j));
+ if (ang>max_aper)
+ max_aper=ang;
+ }
+ }
+ if (max_aper>0.75*Math_PI) {
+ //angle too wide prevent problems and forget
+ oct->normal_accum[ci][0]=0;
+ oct->normal_accum[ci][1]=0;
+ oct->normal_accum[ci][2]=0;
+ }
+ }
}
+
}
oct_idx=oct->next_leaf;
@@ -702,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;
@@ -720,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) {
@@ -727,31 +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
+ 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 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);
+
+ if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) {
+
- float d = p_plot_pos.distance_to(pos);
+ 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) {
- if (d<=r) {
+ float damp = Math::abs(p_plane.normal.dot(normal));
+ intensity*=pow(damp,edge_damp);
+ }
+ }
- float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
- float damp = Math::abs(p_plane.normal.dot(Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2])));
- intensity*=pow(damp,edge_damp);
- //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size);
- 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;
+ //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);
+
+
+ }
}
}
@@ -788,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) {
+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,
@@ -810,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;
@@ -918,8 +1080,13 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
}
+
if (inters) {
+ if (p_only_dist) {
+
+ return p_begin.distance_to(r_point);
+ }
//should check if there is normals first
@@ -933,6 +1100,9 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
}
if (n.dot(r_normal)>0)
+ return -1;
+
+ if (n.dot(r_normal)>0)
r_normal=-r_normal;
@@ -969,6 +1139,20 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
//the multiplication can happen with more detail in the shader
+
+ if (triangle->material) {
+
+ //triangle->get_uv(r_point);
+
+ diffuse_at_point=triangle->material->diffuse.get_color(uv);
+ specular_at_point=triangle->material->specular.get_color(uv);
+ }
+
+
+ diffuse_at_point.r=res_light.r*diffuse_at_point.r;
+ diffuse_at_point.g=res_light.g*diffuse_at_point.g;
+ diffuse_at_point.b=res_light.b*diffuse_at_point.b;
+
float ret=1e6;
if (p_bounces>0) {
@@ -985,18 +1169,6 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
- if (triangle->material) {
-
- //triangle->get_uv(r_point);
-
- diffuse_at_point=triangle->material->diffuse.get_color(uv);
- specular_at_point=triangle->material->specular.get_color(uv);
- }
-
-
- diffuse_at_point.r=res_light.r*diffuse_at_point.r;
- diffuse_at_point.g=res_light.g*diffuse_at_point.g;
- diffuse_at_point.b=res_light.b*diffuse_at_point.b;
specular_at_point.r=res_light.r*specular_at_point.r;
specular_at_point.g=res_light.g*specular_at_point.g;
@@ -1024,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)) {
@@ -1035,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);
}
}
@@ -1043,34 +1215,58 @@ 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=res_light;
+ 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*4;
- if (ret<r) {
+ 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 {
+
+
+ Vector3 c1=r_normal.cross(n).normalized();
+ Vector3 c2=r_normal.cross(c1).normalized();
+ double r1 = double(rand())/RAND_MAX;
+ 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(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);
+ skip=true;
+
+ } else {
+ //plot_light=Color(0,0,0,0);
+ }
}
}
- 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;
}
- return 0;
+ return -1;
}
@@ -1170,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;
- uint32_t oct_idx=leaf_list;
+ //reset
+ while(oct_idx) {
- //untag
- while(oct_idx) {
+ BakedLightBaker::Octant *oct = &octants[oct_idx];
+ oct->texture_x=0;
+ oct->texture_y=0;
+ oct_idx=oct->next_leaf;
- 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 {
- while(oct_idx) {
+ 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;
+ }
- 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;
@@ -1343,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) {
@@ -1353,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) {
@@ -1367,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: {
@@ -1408,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);
}
@@ -1439,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);
}
@@ -1487,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++) {
@@ -1516,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();
@@ -1533,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)
@@ -1543,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]);
@@ -1555,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]={
@@ -1568,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++) {
@@ -1576,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,
@@ -1622,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++) {
@@ -1687,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;
@@ -1753,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;
}
@@ -2220,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);
@@ -2233,6 +2639,7 @@ void BakedLightBaker::clear() {
const double *normptr=norm_arr.ptr();
}
+*/
octant_pool.clear();
octant_pool_size=0;
bvh=NULL;
@@ -2248,12 +2655,14 @@ void BakedLightBaker::clear() {
lights.clear();
triangles.clear();;
endpoint_normal.clear();
+ endpoint_normal_bits.clear();
baked_octree_texture_w=0;
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;
@@ -2278,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 722255a565..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,31 +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;
- BVH **bvh_stack;
+ Map<Vector3,uint64_t> endpoint_normal_bits;
+
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;
@@ -284,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);
+ 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);
@@ -305,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..514f4b6525 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1055,7 +1055,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);
}
@@ -1791,7 +1791,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 +1814,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) {
@@ -2307,7 +2307,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: {
@@ -2683,6 +2683,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 +2707,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();
@@ -2878,7 +2897,7 @@ 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);
value_dialog = memnew( AcceptDialog );
value_dialog->set_title("Set a Value");
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h
index 15ac7b1bb3..6648d486e8 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.h
+++ b/tools/editor/plugins/canvas_item_editor_plugin.h
@@ -289,6 +289,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:
@@ -341,6 +345,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..ed228e9a1c 100644
--- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -13,7 +13,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,6 +28,7 @@ void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
if(p_node==node) {
node=NULL;
hide();
+ canvas_item_editor->get_viewport_control()->update();
}
}
@@ -83,6 +84,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: {
@@ -379,6 +383,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 +398,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_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_editor_plugin.cpp
index 16b9622312..b92acb60f9 100644
--- a/tools/editor/plugins/collision_polygon_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_polygon_editor_plugin.cpp
@@ -40,7 +40,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;
@@ -120,6 +120,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;
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/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp
new file mode 100644
index 0000000000..a3884f9be4
--- /dev/null
+++ b/tools/editor/plugins/mesh_editor_plugin.cpp
@@ -0,0 +1,282 @@
+#include "mesh_editor_plugin.h"
+
+#include "tools/editor/editor_plugin.h"
+#include "tools/editor/editor_node.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/physics_body.h"
+#include "scene/3d/body_shape.h"
+#include "scene/gui/spin_box.h"
+#include "scene/gui/box_container.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/navigation_mesh.h"
+#include "spatial_editor_plugin.h"
+
+void MeshInstanceEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ options->hide();
+ }
+
+}
+
+
+
+void MeshInstanceEditor::edit(MeshInstance *p_mesh) {
+
+ node=p_mesh;
+
+}
+
+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));
+ return;
+ }
+
+ switch(p_option) {
+ case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: {
+
+ Ref<Shape> shape = mesh->create_trimesh_shape();
+ if (shape.is_null())
+ return;
+ StaticBody *body = memnew( StaticBody );
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(shape);
+ body->add_child(cshape);
+ 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");
+ ur->add_do_method(node,"add_child",body);
+ ur->add_do_method(body,"set_owner",owner);
+ ur->add_do_method(cshape,"set_owner",owner);
+ ur->add_do_reference(body);
+ ur->add_undo_method(node,"remove_child",body);
+ ur->commit_action();
+
+ } break;
+ case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {
+
+ Ref<Shape> shape = mesh->create_convex_shape();
+ if (shape.is_null())
+ return;
+ StaticBody *body = memnew( StaticBody );
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(shape);
+ body->add_child(cshape);
+ 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");
+ ur->add_do_method(node,"add_child",body);
+ ur->add_do_method(body,"set_owner",owner);
+ ur->add_do_method(cshape,"set_owner",owner);
+ ur->add_do_reference(body);
+ ur->add_undo_method(node,"remove_child",body);
+ ur->commit_action();
+
+ } break;
+ case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: {
+
+
+ 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;
+ }
+ Ref<Shape> shape = mesh->create_trimesh_shape();
+ if (shape.is_null())
+ return;
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(shape);
+
+ Node *owner = node->get_owner();
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Create Static Trimesh");
+ ur->add_do_method(node->get_parent(),"add_child",cshape);
+ ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
+ ur->add_do_method(cshape,"set_owner",owner);
+ ur->add_do_reference(cshape);
+ ur->add_undo_method(node->get_parent(),"remove_child",cshape);
+ ur->commit_action();
+
+ } break;
+ case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {
+
+
+ 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;
+ }
+ Ref<Shape> shape = mesh->create_convex_shape();
+ if (shape.is_null())
+ return;
+ CollisionShape *cshape = memnew( CollisionShape );
+ cshape->set_shape(shape);
+
+ Node *owner = node->get_owner();
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Create Static Trimesh");
+ ur->add_do_method(node->get_parent(),"add_child",cshape);
+ ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
+ ur->add_do_method(cshape,"set_owner",owner);
+ ur->add_do_reference(cshape);
+ ur->add_undo_method(node->get_parent(),"remove_child",cshape);
+ ur->commit_action();
+
+ } break;
+ case MENU_OPTION_CREATE_NAVMESH: {
+
+
+
+
+ Ref<NavigationMesh> nmesh = memnew( NavigationMesh );
+
+ if (nmesh.is_null())
+ return;
+
+ nmesh->create_from_mesh(mesh);
+ NavigationMeshInstance *nmi = memnew( NavigationMeshInstance );
+ nmi->set_navigation_mesh(nmesh);
+
+ 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");
+
+ ur->add_do_method(node,"add_child",nmi);
+ ur->add_do_method(nmi,"set_owner",owner);
+
+ ur->add_do_reference(nmi);
+ 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() {
+
+
+ options = memnew( MenuButton );
+ //add_child(options);
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(options);
+
+ options->set_text("Mesh");
+ options->get_popup()->add_item("Create Trimesh Static Body",MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
+ options->get_popup()->add_item("Create Convex Static Body",MENU_OPTION_CREATE_STATIC_CONVEX_BODY);
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item("Create Trimesh Collision Sibling",MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
+ 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");
+
+}
+
+
+void MeshInstanceEditorPlugin::edit(Object *p_object) {
+
+ mesh_editor->edit(p_object->cast_to<MeshInstance>());
+}
+
+bool MeshInstanceEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("MeshInstance");
+}
+
+void MeshInstanceEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ mesh_editor->options->show();
+ } else {
+
+ mesh_editor->options->hide();
+ mesh_editor->edit(NULL);
+ }
+
+}
+
+MeshInstanceEditorPlugin::MeshInstanceEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ mesh_editor = memnew( MeshInstanceEditor );
+ editor->get_viewport()->add_child(mesh_editor);
+
+ mesh_editor->options->hide();
+}
+
+
+MeshInstanceEditorPlugin::~MeshInstanceEditorPlugin()
+{
+}
+
+
diff --git a/tools/editor/plugins/mesh_editor_plugin.h b/tools/editor/plugins/mesh_editor_plugin.h
new file mode 100644
index 0000000000..e502b5dc2b
--- /dev/null
+++ b/tools/editor/plugins/mesh_editor_plugin.h
@@ -0,0 +1,74 @@
+#ifndef MESH_EDITOR_PLUGIN_H
+#define MESH_EDITOR_PLUGIN_H
+
+
+#include "tools/editor/editor_plugin.h"
+#include "tools/editor/editor_node.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/gui/spin_box.h"
+
+
+class MeshInstanceEditor : public Node {
+
+ OBJ_TYPE(MeshInstanceEditor, Node );
+
+
+ enum Menu {
+
+ MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
+ MENU_OPTION_CREATE_STATIC_CONVEX_BODY,
+ 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;
+
+
+ Panel *panel;
+ MeshInstance *node;
+
+ LineEdit *surface_source;
+ LineEdit *mesh_source;
+
+
+ void _menu_option(int p_option);
+ void _create_outline_mesh();
+
+friend class MeshInstanceEditorPlugin;
+ MenuButton * options;
+
+protected:
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(MeshInstance *p_mesh);
+ MeshInstanceEditor();
+};
+
+class MeshInstanceEditorPlugin : public EditorPlugin {
+
+ OBJ_TYPE( MeshInstanceEditorPlugin, EditorPlugin );
+
+ MeshInstanceEditor *mesh_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "MeshInstance"; }
+ 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);
+
+ MeshInstanceEditorPlugin(EditorNode *p_node);
+ ~MeshInstanceEditorPlugin();
+
+};
+
+#endif // MESH_EDITOR_PLUGIN_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..49239343a5 100644
--- a/tools/editor/plugins/path_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/path_2d_editor_plugin.cpp
@@ -195,7 +195,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: {
@@ -439,7 +439,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) {
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..27e539d50b 100644
--- a/tools/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -187,6 +187,8 @@ void Polygon2DEditor::_wip_close() {
bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) {
+ if (node==NULL)
+ return false;
switch(p_event.type) {
@@ -701,11 +703,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 +730,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/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..41c84f6e2c 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);
}
diff --git a/tools/editor/plugins/sample_player_editor_plugin.cpp b/tools/editor/plugins/sample_player_editor_plugin.cpp
index fa8a285e4e..405107889c 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") );
}
@@ -64,6 +64,8 @@ void SamplePlayerEditor::_play() {
return;
node->call("play",samples->get_item_text( samples->get_selected() ));
+ stop->set_pressed(false);
+ play->set_pressed(true);
}
void SamplePlayerEditor::_stop() {
@@ -74,6 +76,9 @@ void SamplePlayerEditor::_stop() {
return;
node->call("stop_all");
+ print_line("STOP ALL!!");
+ stop->set_pressed(true);
+ play->set_pressed(false);
}
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 1c87dd0810..55957887dc 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");
}
@@ -209,6 +209,7 @@ 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)));
Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2));
@@ -237,7 +238,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 +385,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),"|"));
+ }
}
@@ -608,6 +635,16 @@ bool ScriptEditor::_test_script_times_on_disk() {
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 +698,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 +720,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.strip_edges().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.strip_edges().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();
@@ -822,7 +1073,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 +1088,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 +1146,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 +1182,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;
@@ -1105,6 +1356,8 @@ void ScriptEditor::ensure_select_current() {
if (!ste)
return;
Ref<Script> script = ste->get_edited_script();
+
+ ste->get_text_edit()->grab_focus();
}
}
@@ -1284,10 +1537,10 @@ void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const
continue;
String code = ste->get_text_edit()->get_text();
- int pos = script->get_language()->find_function(code,p_function);
+ 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;
@@ -1325,7 +1578,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");
@@ -1333,8 +1586,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);
@@ -1342,7 +1595,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_META|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");
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..0349964310 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,7 @@ 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)));
Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2));
@@ -130,24 +131,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(&params);
+ 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 +228,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 +239,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,15 +385,14 @@ 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);
@@ -491,15 +471,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 +517,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 +569,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..0a206c4a45 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp
@@ -28,1082 +28,1518 @@
/*************************************************************************/
#include "shader_graph_editor_plugin.h"
-#if 0
+
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
+#include "spatial_editor_plugin.h"
+
+////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;
+}
-class _ShaderTester : public ShaderCodeGenerator {
-public:
+void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){
- Set<int> *_set;
+ Vector3 val;
+ for(int i=0;i<p_arr.size();i++) {
+ val[i]=p_arr[i].call("get_val");
+ }
- 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() {}
+ 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;
- _ShaderTester() { _set=NULL; }
-};
+}
+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;
+}
+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;
+}
+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;
-void ShaderEditor::edit(Ref<Shader> p_shader) {
+}
+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;
- shader=p_shader;
+}
+void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){
- if (shader.is_null())
- hide();
- else {
- _read_shader_graph();
+ Vector3 val;
+ for(int i=0;i<p_arr.size();i++) {
+ val[i]=p_arr[i].call("get_val");
}
+ 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;
+
}
+void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){
-Size2 ShaderEditor::_get_maximum_size() {
- Size2 max;
+ 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();
- for(List<int>::Element *E=order.front();E;E=E->next()) {
+}
+void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){
- Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) );
+ 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_NODE && click_node==E->get()) {
+}
- pos+=click_motion-click_pos;
- }
- pos+=get_node_size(E->get());
- if (pos.x>max.x)
- max.x=pos.x;
- if (pos.y>max.y)
- max.y=pos.y;
+void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){
- }
- return max;
+ 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){
-Size2 ShaderEditor::get_node_size(int p_node) const {
- 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");
-
- Size2 size = style->get_minimum_size();
-
- int count=1; // title
- count += VisualServer::shader_get_input_count( type) + VisualServer::shader_get_output_count( type);
+}
+void ShaderGraphView::_cube_input_change(int p_id){
- float max_w=font->get_string_size( VisualServer::shader_node_get_type_info(type).name ).width;
- 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 );
+}
+void ShaderGraphView::_variant_edited() {
- 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 );
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) {
+ 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();
+ }
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_INPUT) {
- switch(type) {
+ 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 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: {
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_TEXTURE_INPUT) {
- 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: {
+ 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();
+ }
- RefPtr res = shader_graph.node_get_param(p_node);
- Ref<Texture> texture = res;
- if (texture.is_null() || texture->get_width()==0) {
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_CUBEMAP_INPUT) {
- size.y+=max_w;
- } else {
+ 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();
+ }
- size.y+=max_w * texture->get_height() / texture->get_width();
- }
- } break;
- default: {}
+}
- }
+void ShaderGraphView::_comment_edited(int p_id,Node* p_button) {
- size.x+=max_w;
- size.y+=count*(font->get_height()+get_constant("vseparation","PopupMenu"));
+ 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;
- return size;
}
-Error ShaderEditor::validate_graph() {
+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);
- _ShaderTester st;
- active_nodes.clear();
- st._set=&active_nodes;
- return shader_graph.generate(&st);
+ 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 ShaderEditor::_draw_node(int p_node) {
+void ShaderGraphView::_tex_edited(int p_id,Node* p_button) {
- 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;
+ 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");
+}
- if (click_type==CLICK_NODE && click_node==p_node) {
+void ShaderGraphView::_cube_edited(int p_id,Node* p_button) {
- pos+=click_motion-click_pos;
- }
+ 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");
+}
- RID ci = get_canvas_item();
- style->draw(ci,Rect2(pos,size));
- 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");
+//////////////view/////////////
- font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, VisualServer::shader_node_get_type_info(type).name,font_color_title);
- ofs.y+=h;
- 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;
+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();
- for(int i=0;i<VisualServer::shader_get_input_count(type);i++) {
+ int from_idx=-1;
+ int to_idx=-1;
+ for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
- 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;
+ if (p_from==E->get()->get_name())
+ from_idx=E->key();
+ if (p_to==E->get()->get_name())
+ to_idx=E->key();
}
- for(int i=0;i<VisualServer::shader_get_output_count(type);i++) {
+ ERR_FAIL_COND(from_idx==-1);
+ ERR_FAIL_COND(to_idx==-1);
- 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;
- }
-
- 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);
+ ur->create_action("Connect Graph Nodes");
- } 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: {
+ List<ShaderGraph::Connection> conns;
- 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");
- }
+ 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()) {
- VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid());
- } break;
- default: {}
+ 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();
-void ShaderEditor::_node_param_changed() {
- shader_graph.node_set_param( click_node,property_editor->get_variant() );
- update();
- _write_shader_graph();
}
-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 ShaderGraphView::_disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) {
- for(const List<int>::Element *E=order.back();E;E=E->prev()) {
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- 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 from_idx=-1;
+ int to_idx=-1;
+ for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
- 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;
-
- for(int i=0;i<VisualServer::shader_get_input_count(type);i++) {
+ if (p_from==E->get()->get_name())
+ from_idx=E->key();
+ if (p_to==E->get()->get_name())
+ to_idx=E->key();
+ }
- if (y<h) {
- if (p_slot_index)
- *p_slot_index=i;
- return CLICK_INPUT_SLOT;
- }
- y-=h;
- }
+ ERR_FAIL_COND(from_idx==-1);
+ ERR_FAIL_COND(to_idx==-1);
- for(int i=0;i<VisualServer::shader_get_output_count(type);i++) {
+ if (!graph->is_node_connected(type,from_idx,p_from_slot,to_idx,p_to_slot))
+ return; //nothing to disconnect
- if (y<h) {
- if (p_slot_index)
- *p_slot_index=i;
- return CLICK_OUTPUT_SLOT;
- }
- y-=h;
- }
+ ur->create_action("Disconnect Graph Nodes");
- if (p_click.y<(rect.pos.y+rect.size.height-style->get_margin(MARGIN_BOTTOM)))
- return CLICK_PARAMETER;
- else
- return CLICK_NODE;
+ 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();
- return CLICK_NONE;
}
-Point2 ShaderEditor::_get_slot_pos(int p_node_id,bool p_input,int p_slot) {
+void ShaderGraphView::_node_removed(int p_id) {
- 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;
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Remove Shader Graph Node");
- if(p_input) {
+ 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;
- pos.y+=p_slot*h;
- pos+=Point2( -vec_icon->get_width()/2.0, h/2.0).floor();
- return pos;
- } else {
+ graph->get_node_connections(type,&conns);
+ for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
- pos.y+=VisualServer::shader_get_input_count( shader_graph.node_get_type(p_node_id ) )*h;
+ 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);
+ }
}
-
- 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;
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
}
-void ShaderEditor::_node_edit_property(int p_node) {
-
- 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;
+void ShaderGraphView::_node_moved(const Vector2& p_from, const Vector2& p_to,int p_id) {
- VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node);
- 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;
-
- 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);
+ 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();
+}
- property_editor->popup();
+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);
}
-bool ShaderEditor::has_point(const Point2& p_point) const {
- int n,si;
+void ShaderGraphView::_create_node(int p_id) {
- return _locate_click(p_point,&n,&si)!=CLICK_NONE;
-}
-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) {
+ 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 (click_type!=CLICK_NONE) {
- click_type=CLICK_NONE;
- update();
- } else {
- // try to disconnect/remove
- 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) {
+ switch(graph->node_get_type(type,p_id)) {
- node_popup->clear();
- node_popup->add_item("Disconnect",NODE_DISCONNECT);
- node_popup->set_pos(rclick_pos);
- node_popup->popup();
+ case ShaderGraph::NODE_INPUT: {
- }
+ gn->set_title("Input");
- if (rclick_type==CLICK_NODE) {
- node_popup->clear();
- node_popup->add_item("Remove",NODE_ERASE);
- node_popup->set_pos(rclick_pos);
- node_popup->popup();
- }
+ 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++;
}
- } else {
+ }
- if (p_event.mouse_button.button_index==1 && click_type!=CLICK_NONE) {
+ } 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);
+ }
- switch(click_type) {
- case CLICK_INPUT_SLOT:
- case CLICK_OUTPUT_SLOT: {
+ 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);
+ }
- 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) {
+ 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);
- shader_graph.connect(click_node,click_slot,id,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")));
- Error err = validate_graph();
- if (err==ERR_CYCLIC_LINK)
- shader_graph.disconnect(click_node,click_slot,id,slot);
- _write_shader_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());
- }
- if (click_type==CLICK_INPUT_SLOT && dst_click_type==CLICK_OUTPUT_SLOT) {
- shader_graph.connect(id,slot,click_node,click_slot);
+ } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc)
+ case ShaderGraph::NODE_VEC_SCALAR_OP: {
- Error err = validate_graph();
- if (err==ERR_CYCLIC_LINK)
- shader_graph.disconnect(id,slot,click_node,click_slot);
- _write_shader_graph();
- }
+ gn->set_title("VecScalarOp");
+ static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={
+ "Mul",
+ "Div",
+ "Pow",
+ };
- } 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();
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) {
- } break;
- }
+ ob->add_item(op_name[i],i);
+ }
- click_type=CLICK_NONE;
- update();
- }
+ 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);
}
- }
+ 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);
- case InputEvent::MOUSE_MOTION: {
+ 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")));
- if (p_event.mouse_motion.button_mask&1 && click_type!=CLICK_NONE) {
+ 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());
- click_motion=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- update();
- }
+ } 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: {
- } break;
- }
-}
+ 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")));
-void ShaderEditor::_notification(int p_what) {
+ 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());
- switch(p_what) {
+ } break; // mat4 x mat4
+ case ShaderGraph::NODE_XFORM_VEC_MULT: {
- case NOTIFICATION_DRAW: {
+ gn->set_title("XFVecMult");
- _update_scrollbars();
- //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1));
+ 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));
- for(List<int>::Element *E=order.front();E;E=E->next()) {
+ gn->add_child(button);
- _draw_node(E->get());
- }
+ 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")));
- if (click_type==CLICK_INPUT_SLOT || click_type==CLICK_OUTPUT_SLOT) {
+ 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());
- VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),click_pos,click_motion,Color(0.5,1,0.5,0.8),2);
+ } 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);
}
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
- for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- 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) {
+ 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);
- source+=click_motion-click_pos;
- }
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_child( memnew(Label("in")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
- if (click_type==CLICK_NODE && click_node==c.dst_id) {
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
- dest+=click_motion-click_pos;
- }
- VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),source,dest,col,2);
+ } break; // scalar function (sin: { } break; cos: { } break; etc)
+ case ShaderGraph::NODE_VEC_FUNC: {
- }
- } break;
- }
-}
-void ShaderEditor::_update_scrollbars() {
+ gn->set_title("VecFunc");
+ static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={
+ "Normalize",
+ "Saturate",
+ "Negate",
+ "Reciprocal",
+ "RGB to HSV",
+ "HSV to RGB",
+ };
- Size2 size = get_size();
- Size2 hmin = h_scroll->get_minimum_size();
- Size2 vmin = v_scroll->get_minimum_size();
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) {
- v_scroll->set_begin( Point2(size.width - vmin.width, 0) );
- v_scroll->set_end( Point2(size.width, size.height) );
+ ob->add_item(func_name[i],i);
+ }
- h_scroll->set_begin( Point2( 0, size.height - hmin.height) );
- h_scroll->set_end( Point2(size.width-vmin.width, size.height) );
+ 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_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_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++;
+ }
+ }
+ } 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));
- Size2 min = _get_maximum_size();
+ } break; // comment
- if (min.height < size.height - hmin.height) {
- v_scroll->hide();
- offset.y=0;
- } else {
- 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 {
-
- h_scroll->show();
- h_scroll->set_max(min.width);
- h_scroll->set_page(size.width - vmin.width);
- offset.x=h_scroll->get_val();
- }
-}
+ 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::_scroll_moved() {
- offset.x=h_scroll->get_val();
- offset.y=v_scroll->get_val();
- update();
}
-void ShaderEditor::_bind_methods() {
-
- 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 );
-}
+void ShaderGraphView::_update_graph() {
-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()) {
+ if (block_update)
+ return;
- if (E->get() > larger_id)
- larger_id = E->get();
+ 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());
+ memdelete(E->get());
}
- last_id=larger_id+1;
+ node_map.clear();
- List<Shader::Connection> connections;
- shader->get_connections(&connections);
-
- for(List<Shader::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- Shader::Connection &c=E->get();
- shader_graph.connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
- }
+ if (!graph.is_valid())
+ return;
- validate_graph();
- update();
-}
-void ShaderEditor::_write_shader_graph() {
+ List<int> nl;
+ graph->get_node_list(type,&nl);
- shader->clear();
- List<int> nodes;
- shader_graph.get_node_list(&nodes);
- for(List<int>::Element *E=nodes.front();E;E=E->next()) {
+ for(List<int>::Element *E=nl.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()) ) );
+ _create_node(E->get());
}
+ graph_edit->clear_connections();
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
+ List<ShaderGraph::Connection> connections;
+ graph->get_node_connections(type,&connections);
for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
- const ShaderGraph::Connection &c=E->get();
- shader->connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
+ 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);
}
-}
-void ShaderEditor::_add_node_from_text(const String& p_text) {
- 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)";
- _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) {
-
- _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 ShaderEditor::_post_item(int p_item) {
-
- _add_node_from_text(post_popup->get_item_text(p_item));
-}
-
-
-void ShaderEditor::_node_menu_item(int p_item) {
-
- switch(p_item) {
-
- case GRAPH_ADD_NODE: {
- add_popup->popup_centered_ratio();
- validate_graph();
- } break;
- case NODE_DISCONNECT: {
-
- if (rclick_type==CLICK_INPUT_SLOT) {
-
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
- for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- const ShaderGraph::Connection &c=E->get();
- if( c.dst_id==rclick_node && c.dst_slot==rclick_slot) {
+void ShaderGraphView::_sg_updated() {
- shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
- }
- }
- update();
- _write_shader_graph();
- validate_graph();
- }
-
- if (rclick_type==CLICK_OUTPUT_SLOT) {
-
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
- for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- const ShaderGraph::Connection &c=E->get();
- if( c.src_id==rclick_node && c.src_slot==rclick_slot) {
-
- shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
- }
- }
- update();
- _write_shader_graph();
- validate_graph();
- }
-
- } break;
- case NODE_ERASE: {
-
- order.erase(rclick_node);
- shader_graph.node_remove(rclick_node);
- update();
- _write_shader_graph();
- validate_graph();
- } break;
- case GRAPH_CLEAR: {
-
- order.clear();
- shader_graph.clear();
- last_id=1;
- last_x=20;
- last_y=20;
- update();
- _write_shader_graph();
- validate_graph();
-
- } break;
+ 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;
}
}
-void ShaderEditor::_node_add(VisualServer::ShaderNodeType p_type) {
-
- shader_graph.node_add(p_type,last_id );
- shader_graph.node_set_pos(last_id ,last_x,last_y);
- String test_param;
-
- switch(p_type) {
- case VS::NODE_PARAMETER: {
+void ShaderGraphView::set_graph(Ref<ShaderGraph> p_graph){
- test_param="param";
- } break;
- case VS::NODE_VEC_PARAMETER: {
-
- test_param="vec";
- } break;
- case VS::NODE_COLOR_PARAMETER: {
- test_param="color";
- } break;
- case VS::NODE_TEXTURE_PARAMETER: {
-
- test_param="tex";
- } break;
- case VS::NODE_TEXTURE_2D_PARAMETER: {
-
- test_param="tex2D";
- } break;
- case VS::NODE_TEXTURE_CUBE_PARAMETER: {
-
- test_param="cubemap";
- } break;
- case VS::NODE_TRANSFORM_PARAMETER: {
- test_param="xform";
- } break;
- case VS::NODE_LABEL: {
-
- test_param="label";
- } break;
+ 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();
- if(test_param!="") {
+}
- int iter=0;
- List<int> l;
+void ShaderGraphView::_notification(int p_what) {
- shader_graph.get_node_list(&l);
+ if (p_what==NOTIFICATION_ENTER_TREE) {
- 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()) {
+ 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;
+ }
+ }
+ 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;
- String param = shader_graph.node_get_param( E->get() );
- if (param==test) {
- found=true;
- break;
- }
}
+ }
- } while (found);
-
-
- shader_graph.node_set_param(last_id,test);
-
+ if (valid)
+ break;
}
- 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();
+ 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 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() ;
+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("_sg_updated",&ShaderGraphView::_sg_updated);
}
-ShaderEditor::ShaderEditor() {
-
- 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) );
-
- add_child( menu_panel );
-
- PopupMenu *p;
- List<PropertyInfo> defaults;
-
- MenuButton* node_menu = memnew( MenuButton );
- node_menu->set_text("Graph");
- node_menu->set_pos( Point2( 5,0) );
- menu_panel->add_child( node_menu );
-
- 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");
-
- 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);
-
- int 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++);
- }
- p->add_separator();
- id++;
-
- defaults.clear();
- VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_VERTEX,&defaults);
-
- for(int i=0;i<defaults.size();i++) {
-
- p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
- }
+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("");
+}
- 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++) {
+//////////////edit//////////////
+void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) {
- p->add_item("In: "+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);
}
- 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 ShaderGraphEditor::_add_node(int p_type) {
- p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
- }
+ ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab());
- fragment_popup=p;
- fragment_popup->connect("item_pressed", this,"_fragment_item");
+ graph_edits[shader_type]->add_node(p_type);
+}
- MenuButton* post_menu = memnew( MenuButton );
- post_menu->set_text("Post");
- post_menu->set_pos( Point2( 161,0) );
- menu_panel->add_child( post_menu );
- 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++) {
+void ShaderGraphEditor::_notification(int p_what) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
- p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
- }
- p->add_separator();
- id++;
+ for(int i=0;i<ShaderGraph::NODE_TYPE_MAX;i++) {
- defaults.clear();
- VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_POST_PROCESS,&defaults);
+ if (i==ShaderGraph::NODE_OUTPUT)
+ 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");
- for(int i=0;i<defaults.size();i++) {
- p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
}
+}
- post_popup=p;
- post_popup->connect("item_pressed", this,"_post_item");
-
-
- /* 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)
+ "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)
+ "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() {
+
+ 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");
+ return p_object->is_type("ShaderGraph");
}
-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) {
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 );
shader_editor->hide();
+ 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..bd983c59be 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.h
+++ b/tools/editor/plugins/shader_graph_editor_plugin.h
@@ -29,122 +29,124 @@
#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 );
-
- enum MenuAction {
-
- GRAPH_ADD_NODE,
- GRAPH_CLEAR,
- NODE_DISCONNECT,
- NODE_ERASE,
-
- };
-
- enum ClickType {
- CLICK_NONE,
- CLICK_NODE,
- CLICK_INPUT_SLOT,
- CLICK_OUTPUT_SLOT,
- CLICK_PARAMETER
- };
-
- 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;
+
+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;
+
+ void _update_graph();
+ void _create_node(int p_id);
+
+
+
+ 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 _sg_updated();
+ Map<int,GraphNode*> node_map;
protected:
void _notification(int p_what);
- void _input_event(InputEvent p_event);
static void _bind_methods();
public:
- void edit(Ref<Shader> p_shader);
- ShaderEditor();
+ 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 ShaderEditorPlugin : public EditorPlugin {
+class ShaderGraphEditor : public VBoxContainer {
- OBJ_TYPE( ShaderEditorPlugin, EditorPlugin );
+ OBJ_TYPE(ShaderGraphEditor,VBoxContainer);
- ShaderEditor *shader_editor;
+ MenuButton *menu;
+ TabContainer *tabs;
+ ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX];
+ static const char* node_names[ShaderGraph::NODE_TYPE_MAX];
+
+ void _add_node(int p_type);
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void edit(Ref<ShaderGraph> p_shader);
+ ShaderGraphEditor();
+};
+
+class ShaderGraphEditorPlugin : public EditorPlugin {
+
+ OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin );
+
+ 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);
+ ~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 a5cddc20e6..87bd8105af 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++) {
@@ -535,6 +535,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 +732,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());
@@ -860,10 +868,19 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
_edit.snap=false;
_edit.mode=TRANSFORM_NONE;
+
//gizmo has priority over everything
+ bool can_select_gizmos=true;
+
+ {
+ int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
+ can_select_gizmos = view_menu->get_popup()->is_item_checked( idx );
+ }
+
+
- if (spatial_editor->get_selected()) {
+ if (can_select_gizmos && spatial_editor->get_selected()) {
Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo();
if (seg.is_valid()) {
@@ -1420,10 +1437,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;
@@ -1702,7 +1728,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");
@@ -1925,6 +1951,27 @@ void SpatialEditorViewport::_menu_option(int p_option) {
call_deferred("update_transform_gizmo_view");
} break;
+ case VIEW_AUDIO_LISTENER: {
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
+ bool current = view_menu->get_popup()->is_item_checked( idx );
+ current=!current;
+ viewport->set_as_audio_listener(current);
+ view_menu->get_popup()->set_item_checked( idx, current );
+
+ } break;
+ case VIEW_GIZMOS: {
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
+ bool current = view_menu->get_popup()->is_item_checked( idx );
+ current=!current;
+ if (current)
+ camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) );
+ else
+ camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_GRID_LAYER) );
+ view_menu->get_popup()->set_item_checked( idx, current );
+
+ } break;
}
@@ -1941,12 +1988,12 @@ void SpatialEditorViewport::_preview_exited_scene() {
void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
- uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx);
+ 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);
@@ -1954,7 +2001,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);
@@ -1971,7 +2018,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)
@@ -1982,7 +2029,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();
@@ -2055,6 +2102,13 @@ void SpatialEditorViewport::set_state(const Dictionary& p_state) {
_menu_option(VIEW_PERSPECTIVE);
if (env != camera->get_environment().is_valid())
_menu_option(VIEW_ENVIRONMENT);
+ if (p_state.has("listener")) {
+ bool listener = p_state["listener"];
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
+ viewport->set_as_audio_listener(listener);
+ view_menu->get_popup()->set_item_checked( idx, listener );
+ }
}
@@ -2068,6 +2122,7 @@ Dictionary SpatialEditorViewport::get_state() const {
d["distance"]=cursor.distance;
d["use_environment"]=camera->get_environment().is_valid();
d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
+ d["listener"]=viewport->is_audio_listener();
return d;
}
@@ -2098,6 +2153,9 @@ void SpatialEditorViewport::reset() {
cursor.distance=4;
cursor.region_select=false;
+
+
+
}
SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
@@ -2122,7 +2180,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
surface->set_area_as_parent_rect();
camera = memnew(Camera);
camera->set_disable_gizmo(true);
- camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+p_index)) );
+ camera->set_visible_layers( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+p_index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) );
//camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
viewport->add_child(camera);
camera->make_current();
@@ -2148,6 +2206,12 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_check_item("Environment",VIEW_ENVIRONMENT);
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT),true);
view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_check_item("Audio Listener",VIEW_AUDIO_LISTENER);
+ view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_check_item("Gizmos",VIEW_GIZMOS);
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_GIZMOS),true);
+
+ view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_item("Selection (F)",VIEW_CENTER_TO_SELECTION);
view_menu->get_popup()->add_item("Align with view (Ctrl+Shift+F)",VIEW_ALIGN_SELECTION_WITH_VIEW);
view_menu->get_popup()->connect("item_pressed",this,"_menu_option");
@@ -2163,6 +2227,12 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
previewing=NULL;
preview=NULL;
gizmo_scale=1.0;
+
+ if (p_index==0) {
+ view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER),true);
+ viewport->set_as_audio_listener(true);
+ }
+
EditorSettings::get_singleton()->connect("settings_changed",this,"update_transform_gizmo_view");
}
@@ -2260,7 +2330,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);
@@ -2322,6 +2392,10 @@ Dictionary SpatialEditor::get_state() const {
vc=3;
else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) ))
vc=4;
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) ))
+ vc=5;
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) ))
+ vc=6;
d["viewport_mode"]=vc;
Array vpdata;
@@ -2332,11 +2406,16 @@ Dictionary SpatialEditor::get_state() const {
d["viewports"]=vpdata;
d["default_light"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT) );;
+ d["ambient_light_color"]=settings_ambient_color->get_color();
+
+ d["default_srgb"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB) );;
d["show_grid"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID) );;
d["show_origin"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN) );;
d["fov"]=get_fov();
d["znear"]=get_znear();
d["zfar"]=get_zfar();
+ d["deflight_rot_x"]=settings_default_light_rot_x;
+ d["deflight_rot_y"]=settings_default_light_rot_y;
return d;
}
@@ -2363,6 +2442,10 @@ void SpatialEditor::set_state(const Dictionary& p_state) {
_menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
else if (vc==4)
_menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
+ else if (vc==5)
+ _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
+ else if (vc==6)
+ _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
Array vp = d["viewports"];
ERR_FAIL_COND(vp.size()>4);
@@ -2373,11 +2456,12 @@ void SpatialEditor::set_state(const Dictionary& p_state) {
if (d.has("zfar"))
- settings_zfar->set_text(d["zfar"]);
+ settings_zfar->set_val(float(d["zfar"]));
if (d.has("znear"))
- settings_znear->set_text(d["znear"]);
+ settings_znear->set_val(float(d["znear"]));
if (d.has("fov"))
- settings_fov->set_text(d["fov"]);
+ settings_fov->set_val(float(d["fov"]));
+
if (d.has("default_light")) {
bool use = d["default_light"];
@@ -2387,7 +2471,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);
}
@@ -2395,7 +2479,17 @@ void SpatialEditor::set_state(const Dictionary& p_state) {
}
}
+ if (d.has("ambient_light_color")) {
+ settings_ambient_color->set_color(d["ambient_light_color"]);
+ viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,d["ambient_light_color"]);
+ }
+ if (d.has("default_srgb")) {
+ bool use = d["default_srgb"];
+
+ viewport_environment->set_enable_fx(Environment::FX_SRGB,use);
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB), use );
+ }
if (d.has("show_grid")) {
bool use = d["show_grid"];
@@ -2413,6 +2507,12 @@ void SpatialEditor::set_state(const Dictionary& p_state) {
}
}
+ if (d.has("deflight_rot_x"))
+ settings_default_light_rot_x=d["deflight_rot_x"];
+ if (d.has("deflight_rot_y"))
+ settings_default_light_rot_y=d["deflight_rot_y"];
+
+ _update_default_light_angle();
}
@@ -2573,13 +2673,31 @@ 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();
}
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), light_instance.is_valid() );
} break;
+ case MENU_VIEW_USE_DEFAULT_SRGB: {
+
+ bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
+
+ if (is_checked) {
+ viewport_environment->set_enable_fx(Environment::FX_SRGB,false);
+ } else {
+ viewport_environment->set_enable_fx(Environment::FX_SRGB,true);
+ }
+
+ is_checked = ! is_checked;
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), is_checked );
+
+
+ } break;
case MENU_VIEW_USE_1_VIEWPORT: {
for(int i=1;i<4;i++) {
@@ -2593,6 +2711,8 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
} break;
case MENU_VIEW_USE_2_VIEWPORTS: {
@@ -2615,6 +2735,32 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), true );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
+
+ } break;
+ case MENU_VIEW_USE_2_VIEWPORTS_ALT: {
+
+ for(int i=1;i<4;i++) {
+
+ if (i==1 || i==3)
+ viewports[i]->hide();
+ else
+ viewports[i]->show();
+
+
+ }
+ viewports[0]->set_area_as_parent_rect();
+ viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ viewports[2]->set_area_as_parent_rect();
+ viewports[2]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
} break;
case MENU_VIEW_USE_3_VIEWPORTS: {
@@ -2639,6 +2785,34 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), true );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
+
+ } break;
+ case MENU_VIEW_USE_3_VIEWPORTS_ALT: {
+
+ for(int i=1;i<4;i++) {
+
+ if (i==1)
+ viewports[i]->hide();
+ else
+ viewports[i]->show();
+ }
+ viewports[0]->set_area_as_parent_rect();
+ viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
+ viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ viewports[2]->set_area_as_parent_rect();
+ viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
+ viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ viewports[3]->set_area_as_parent_rect();
+ viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), true );
} break;
case MENU_VIEW_USE_4_VIEWPORTS: {
@@ -2664,12 +2838,14 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
} break;
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 );
@@ -2679,7 +2855,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 );
@@ -2688,7 +2864,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 );
@@ -2697,7 +2873,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 );
@@ -2732,7 +2908,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
} break;
case MENU_VIEW_CAMERA_SETTINGS: {
- settings_dialog->popup_centered(Size2(200,160));
+ settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size()+Size2(50,50));
} break;
}
@@ -2744,7 +2920,8 @@ 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());
+
light_transform.rotate(Vector3(1,0,0),Math_PI/5.0);
@@ -2804,11 +2981,13 @@ 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;
VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i],VS::INSTANCE_FLAG_VISIBLE,false);
VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i],VS::INSTANCE_FLAG_CAST_SHADOW,false);
+ VS::get_singleton()->instance_set_layer_mask(grid_instance[i],1<<SpatialEditorViewport::GIZMO_GRID_LAYER);
}
@@ -2826,7 +3005,9 @@ 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);
@@ -2861,7 +3042,9 @@ 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);
@@ -3133,22 +3316,26 @@ void SpatialEditor::_notification(int p_what) {
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT),get_icon("Panels1","EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS),get_icon("Panels2","EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT),get_icon("Panels2Alt","EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS),get_icon("Panels3","EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT),get_icon("Panels3Alt","EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS),get_icon("Panels4","EditorIcons"));
_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 );
@@ -3250,8 +3437,12 @@ void SpatialEditor::_toggle_maximize_view(Object* p_viewport) {
_menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS) ))
_menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS);
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) ))
+ _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS) ))
_menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) ))
+ _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) ))
_menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
}
@@ -3276,7 +3467,8 @@ void SpatialEditor::_bind_methods() {
// ObjectTypeDB::bind_method("_update_selection",&SpatialEditor::_update_selection);
ObjectTypeDB::bind_method("_get_editor_data",&SpatialEditor::_get_editor_data);
ObjectTypeDB::bind_method("_request_gizmo",&SpatialEditor::_request_gizmo);
-
+ ObjectTypeDB::bind_method("_default_light_angle_input",&SpatialEditor::_default_light_angle_input);
+ ObjectTypeDB::bind_method("_update_ambient_light_color",&SpatialEditor::_update_ambient_light_color);
ObjectTypeDB::bind_method("_toggle_maximize_view",&SpatialEditor::_toggle_maximize_view);
ADD_SIGNAL( MethodInfo("transform_key_request") );
@@ -3286,9 +3478,9 @@ void SpatialEditor::_bind_methods() {
void SpatialEditor::clear() {
- settings_fov->set_text(EDITOR_DEF("3d_editor/default_fov",60.0));
- settings_znear->set_text(EDITOR_DEF("3d_editor/default_z_near",0.1));
- settings_zfar->set_text(EDITOR_DEF("3d_editor/default_z_far",1500.0));
+ settings_fov->set_val(EDITOR_DEF("3d_editor/default_fov",60.0));
+ settings_znear->set_val(EDITOR_DEF("3d_editor/default_z_near",0.1));
+ settings_zfar->set_val(EDITOR_DEF("3d_editor/default_z_far",1500.0));
for(int i=0;i<4;i++) {
viewports[i]->reset();
@@ -3307,11 +3499,59 @@ void SpatialEditor::clear() {
}
}
+ for(int i=0;i<4;i++) {
+
+ viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER),i==0);
+ viewports[i]->viewport->set_as_audio_listener(i==0);
+ }
+
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true );
+ settings_default_light_rot_x=Math_PI*0.3;
+ settings_default_light_rot_y=Math_PI*0.2;
+
+ viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,Color(0.15,0.15,0.15));
+ settings_ambient_color->set_color(Color(0.15,0.15,0.15));
+ if (!light_instance.is_valid())
+ _menu_item_pressed(MENU_VIEW_USE_DEFAULT_LIGHT);
+
+ _update_default_light_angle();
+
+
+}
+
+
+void SpatialEditor::_update_ambient_light_color(const Color& p_color) {
+
+ viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,settings_ambient_color->get_color());
}
+void SpatialEditor::_update_default_light_angle() {
+
+ Transform t;
+ t.basis.rotate(Vector3(1,0,0),settings_default_light_rot_x);
+ t.basis.rotate(Vector3(0,1,0),settings_default_light_rot_y);
+ settings_dlight->set_transform(t);
+ if (light_instance.is_valid()) {
+ VS::get_singleton()->instance_set_transform(light_instance,t);
+ }
+
+}
+
+void SpatialEditor::_default_light_angle_input(const InputEvent& p_event) {
+
+
+ if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&(0x1|0x2|0x4)) {
+
+ settings_default_light_rot_y = Math::fposmod(settings_default_light_rot_y - p_event.mouse_motion.relative_x*0.01,Math_PI*2.0);
+ settings_default_light_rot_x = Math::fposmod(settings_default_light_rot_x - p_event.mouse_motion.relative_y*0.01,Math_PI*2.0);
+ _update_default_light_angle();
+ }
+
+}
+
+
SpatialEditor::SpatialEditor(EditorNode *p_editor) {
@@ -3407,12 +3647,15 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
p = view_menu->get_popup();
p->add_check_item("Use Default Light",MENU_VIEW_USE_DEFAULT_LIGHT);
+ 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("3 Viewports",MENU_VIEW_USE_3_VIEWPORTS,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);
@@ -3507,42 +3750,68 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
settings_dialog = memnew( ConfirmationDialog );
settings_dialog->set_title("Viewport Settings");
add_child(settings_dialog);
- l = memnew(Label);
- l->set_text("Perspective FOV (deg.):");
- l->set_pos(Point2(5,5));
- settings_dialog->add_child(l);
-
- settings_fov = memnew( LineEdit );
- settings_fov->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- settings_fov->set_begin( Point2(15,22) );
- settings_fov->set_end( Point2(15,35) );
- settings_fov->set_text(EDITOR_DEF("3d_editor/default_fov",60.0));
- settings_dialog->add_child(settings_fov);
-
- l = memnew(Label);
- l->set_text("View Z-Near");
- l->set_pos(Point2(5,45));
- settings_dialog->add_child(l);
-
- settings_znear = memnew( LineEdit );
- settings_znear->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- settings_znear->set_begin( Point2(15,62) );
- settings_znear->set_end( Point2(15,75) );
- settings_znear->set_text(EDITOR_DEF("3d_editor/default_z_near",0.1));
- settings_dialog->add_child(settings_znear);
-
-
- l = memnew(Label);
- l->set_text("View Z-Far");
- l->set_pos(Point2(5,85));
- settings_dialog->add_child(l);
-
- settings_zfar = memnew( LineEdit );
- settings_zfar->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- settings_zfar->set_begin( Point2(15,102) );
- settings_zfar->set_end( Point2(15,115) );
- settings_zfar->set_text(EDITOR_DEF("3d_editor/default_z_far",1500.0));
- settings_dialog->add_child(settings_zfar);
+ settings_vbc = memnew( VBoxContainer );
+ settings_vbc->set_custom_minimum_size(Size2(200,0));
+ settings_dialog->add_child(settings_vbc);
+ settings_dialog->set_child_rect(settings_vbc);
+
+
+
+ settings_light_base = memnew( Control );
+ settings_light_base->set_custom_minimum_size(Size2(128,128));
+ settings_light_base->connect("input_event",this,"_default_light_angle_input");
+ settings_vbc->add_margin_child("Default Light Normal:",settings_light_base);
+ settings_light_vp = memnew( Viewport );
+ settings_light_vp->set_use_own_world(true);
+ settings_light_base->add_child(settings_light_vp);
+
+ settings_dlight = memnew( DirectionalLight );
+ settings_light_vp->add_child(settings_dlight);
+ settings_sphere = memnew( ImmediateGeometry );
+ settings_sphere->begin(Mesh::PRIMITIVE_TRIANGLES,Ref<Texture>());
+ settings_sphere->set_color(Color(1,1,1));
+ settings_sphere->add_sphere(32,16,1);
+ settings_sphere->end();
+ settings_light_vp->add_child(settings_sphere);
+ settings_camera = memnew( Camera );
+ settings_light_vp->add_child(settings_camera);
+ settings_camera->set_translation(Vector3(0,0,2));
+ settings_camera->set_orthogonal(2.1,0.1,5);
+
+ settings_default_light_rot_x=Math_PI*0.3;
+ settings_default_light_rot_y=Math_PI*0.2;
+
+
+
+ settings_ambient_color = memnew( ColorPickerButton );
+ settings_vbc->add_margin_child("Ambient Light Color:",settings_ambient_color);
+ settings_ambient_color->connect("color_changed",this,"_update_ambient_light_color");
+
+ viewport_environment->set_enable_fx(Environment::FX_AMBIENT_LIGHT,true);
+ viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,Color(0.15,0.15,0.15));
+ settings_ambient_color->set_color(Color(0.15,0.15,0.15));
+
+
+ settings_fov = memnew( SpinBox );
+ settings_fov->set_max(179);
+ settings_fov->set_min(1);
+ settings_fov->set_step(0.01);
+ settings_fov->set_val(EDITOR_DEF("3d_editor/default_fov",60.0));
+ settings_vbc->add_margin_child("Perspective FOV (deg.):",settings_fov);
+
+ settings_znear = memnew( SpinBox );
+ settings_znear->set_max(10000);
+ settings_znear->set_min(0.1);
+ settings_znear->set_step(0.01);
+ settings_znear->set_val(EDITOR_DEF("3d_editor/default_z_near",0.1));
+ settings_vbc->add_margin_child("View Z-Near:",settings_znear);
+
+ settings_zfar = memnew( SpinBox );
+ settings_zfar->set_max(10000);
+ settings_zfar->set_min(0.1);
+ settings_zfar->set_step(0.01);
+ settings_zfar->set_val(EDITOR_DEF("3d_editor/default_z_far",1500));
+ settings_vbc->add_margin_child("View Z-Far:",settings_zfar);
//settings_dialog->get_cancel()->hide();
/* XFORM DIALOG */
diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h
index 4bbddbac58..646a4d2d86 100644
--- a/tools/editor/plugins/spatial_editor_plugin.h
+++ b/tools/editor/plugins/spatial_editor_plugin.h
@@ -32,6 +32,8 @@
#include "tools/editor/editor_plugin.h"
#include "tools/editor/editor_node.h"
#include "scene/3d/visual_instance.h"
+#include "scene/3d/immediate_geometry.h"
+#include "scene/3d/light.h"
#include "scene/gui/panel_container.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
@@ -65,7 +67,7 @@ public:
class SpatialEditorViewport : public Control {
OBJ_TYPE( SpatialEditorViewport, Control );
-
+friend class SpatialEditor;
enum {
VIEW_TOP,
@@ -78,12 +80,17 @@ class SpatialEditorViewport : public Control {
VIEW_ALIGN_SELECTION_WITH_VIEW,
VIEW_PERSPECTIVE,
VIEW_ENVIRONMENT,
- VIEW_ORTHOGONAL
+ VIEW_ORTHOGONAL,
+ VIEW_AUDIO_LISTENER,
+ VIEW_GIZMOS,
};
+public:
enum {
- GIZMO_BASE_LAYER=25
+ GIZMO_BASE_LAYER=27,
+ GIZMO_EDIT_LAYER=26,
+ GIZMO_GRID_LAYER=25
};
-
+private:
int index;
void _menu_option(int p_option);
Size2 prev_size;
@@ -137,6 +144,12 @@ class SpatialEditorViewport : public Control {
};
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,
@@ -343,9 +356,12 @@ private:
MENU_TRANSFORM_DIALOG,
MENU_VIEW_USE_1_VIEWPORT,
MENU_VIEW_USE_2_VIEWPORTS,
+ MENU_VIEW_USE_2_VIEWPORTS_ALT,
MENU_VIEW_USE_3_VIEWPORTS,
+ MENU_VIEW_USE_3_VIEWPORTS_ALT,
MENU_VIEW_USE_4_VIEWPORTS,
MENU_VIEW_USE_DEFAULT_LIGHT,
+ MENU_VIEW_USE_DEFAULT_SRGB,
MENU_VIEW_DISPLAY_NORMAL,
MENU_VIEW_DISPLAY_WIREFRAME,
MENU_VIEW_DISPLAY_OVERDRAW,
@@ -379,15 +395,28 @@ private:
LineEdit *xform_scale[3];
OptionButton *xform_type;
- LineEdit *settings_fov;
- LineEdit *settings_znear;
- LineEdit *settings_zfar;
+ VBoxContainer *settings_vbc;
+ SpinBox *settings_fov;
+ SpinBox *settings_znear;
+ SpinBox *settings_zfar;
+ DirectionalLight *settings_dlight;
+ ImmediateGeometry *settings_sphere;
+ Camera *settings_camera;
+ float settings_default_light_rot_x;
+ float settings_default_light_rot_y;
+
+ Control *settings_light_base;
+ Viewport *settings_light_vp;
+ ColorPickerButton *settings_ambient_color;
+ Image settings_light_dir_image;
+
void _xform_dialog_action();
void _menu_item_pressed(int p_option);
HBoxContainer *hbc_menu;
+
//
//
void _generate_selection_box();
@@ -417,6 +446,10 @@ private:
SpatialEditorGizmos *gizmos;
SpatialEditor();
+ void _update_ambient_light_color(const Color& p_color);
+ void _update_default_light_angle();
+ void _default_light_angle_input(const InputEvent& p_event);
+
protected:
@@ -433,9 +466,9 @@ public:
static SpatialEditor *get_singleton() { return singleton; }
void snap_cursor_to_plane(const Plane& p_plane);
- float get_znear() const { return settings_znear->get_text().to_double(); }
- float get_zfar() const { return settings_zfar->get_text().to_double(); }
- float get_fov() const { return settings_fov->get_text().to_double(); }
+ float get_znear() const { return settings_znear->get_val(); }
+ float get_zfar() const { return settings_zfar->get_val(); }
+ float get_fov() const { return settings_fov->get_val(); }
Transform get_gizmo_transform() const { return gizmo.transform; }
bool is_gizmo_visible() const { return gizmo.visible; }
diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.cpp b/tools/editor/plugins/sprite_frames_editor_plugin.cpp
index a26fab0f9a..e04d9dfddb 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") );
}
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/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp
index 09f26c8ca0..a7e6a0d1f9 100644
--- a/tools/editor/plugins/tile_map_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_map_editor_plugin.cpp
@@ -42,7 +42,6 @@ void TileMapEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
- pane_drag->connect("dragged", this,"_pane_drag");
mirror_x->set_icon( get_icon("MirrorX","EditorIcons"));
mirror_y->set_icon( get_icon("MirrorY","EditorIcons"));
@@ -166,7 +165,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
Matrix32 xform_inv = xform.affine_inverse();
- Vector2 snap = Vector2(1,1)*node->get_cell_size();
+ Vector2 snap = node->get_cell_size();
switch(p_event.type) {
@@ -218,7 +217,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
if (mb.mod.shift) {
tool=TOOL_SELECTING;
- selection_begin =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
+ selection_begin =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y)));
selection.pos=selection_begin;
selection.size=Point2(0,0);
selection_active=true;
@@ -229,7 +228,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
int id = get_selected_tile();
if (id!=TileMap::INVALID_CELL) {
tool=TOOL_PAINTING;
- Point2i local =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
+ 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);
@@ -278,7 +277,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
} else if (mb.pressed && tool==TOOL_NONE) {
tool=TOOL_ERASING;
- Point2i local =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
+ 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);
@@ -322,7 +321,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
const InputEventMouseMotion &mm=p_event.mouse_motion;
- Point2i new_over_tile = (xform_inv.xform(Point2(mm.x,mm.y))/snap).floor();
+ Point2i new_over_tile = node->world_to_map(xform_inv.xform(Point2(mm.x,mm.y)));//(xform_inv.xform(Point2(mm.x,mm.y))/snap).floor();
if (new_over_tile!=over_tile) {
over_tile=new_over_tile;
@@ -469,44 +468,104 @@ void TileMapEditor::_canvas_draw() {
if (!node)
return;
- int cell_size=node->get_cell_size();
+ Size2 cell_size=node->get_cell_size();
+ Matrix32 cell_xf = node->get_cell_transform();
Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
Matrix32 xform_inv = xform.affine_inverse();
Size2 screen_size=canvas_item_editor->get_size();
- Rect2 aabb;
- aabb.pos=xform_inv.xform(Vector2());
- aabb.expand_to(xform_inv.xform(Vector2(0,screen_size.height)));
- aabb.expand_to(xform_inv.xform(Vector2(screen_size.width,0)));
- aabb.expand_to(xform_inv.xform(screen_size));
- Rect2i si=aabb;
+ {
+ Rect2 aabb;
+ aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
+ aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
+ aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
+ aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
+ Rect2i si=aabb.grow(1.0);
- for(int i=(si.pos.x/cell_size)-1;i<=(si.pos.x+si.size.x)/cell_size;i++) {
+ if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) {
- int ofs = i*cell_size;
+ for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
- Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
- canvas_item_editor->draw_line(xform.xform(Point2(ofs,si.pos.y)),xform.xform(Point2(ofs,si.pos.y+si.size.y)),col,1);
+ Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y)));
+ Vector2 to = xform.xform(node->map_to_world(Vector2(i,si.pos.y+si.size.y+1)));
- }
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+
+ }
+ } else {
+
+
+ for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
+
+ for(int j=(si.pos.y)-1;j<=(si.pos.y+si.size.y);j++) {
+
+ Vector2 ofs;
+ if (ABS(j)&1) {
+ ofs=cell_xf[0]*0.5;
+ }
+
+ Vector2 from = xform.xform(node->map_to_world(Vector2(i,j),true)+ofs);
+ Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs);
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+ }
+
+ }
+ }
+
+ if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) {
+
+ for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
+
+ Vector2 from = xform.xform(node->map_to_world(Vector2(si.pos.x,i)));
+ Vector2 to = xform.xform(node->map_to_world(Vector2(si.pos.x+si.size.x+1,i)));
+
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+
+ }
+ } else {
- for(int i=(si.pos.y/cell_size)-1;i<=(si.pos.y+si.size.y)/cell_size;i++) {
- int ofs = i*cell_size;
+ for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
+
+ for(int j=(si.pos.x)-1;j<=(si.pos.x+si.size.x);j++) {
+
+ Vector2 ofs;
+ if (ABS(j)&1) {
+ ofs=cell_xf[1]*0.5;
+ }
+
+ Vector2 from = xform.xform(node->map_to_world(Vector2(j,i),true)+ofs);
+ Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs);
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+ }
+
+ }
+
+
+
+ }
+/*
+ for(int i=(si.pos.y/cell_size.y)-1;i<=(si.pos.y+si.size.y)/cell_size.y;i++) {
+
+ int ofs = i*cell_size.y;
Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
- canvas_item_editor->draw_line(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),col,1);
+ canvas_item_editor->draw_line(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),col,1);*/
}
if (selection_active) {
Vector<Vector2> points;
- points.push_back( xform.xform( selection.pos * cell_size) );
- points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,0)) * cell_size) );
- points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,selection.size.y+1)) * cell_size) );
- points.push_back( xform.xform( (selection.pos+Point2(0,selection.size.y+1)) * cell_size) );
+ points.push_back( xform.xform( node->map_to_world(( selection.pos ) )));
+ points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,0)) ) ));
+ points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,selection.size.y+1)) ) ));
+ points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(0,selection.size.y+1)) ) ));
Color col=Color(0.2,0.8,1,0.4);
canvas_item_editor->draw_colored_polygon(points,col);
@@ -515,15 +574,22 @@ void TileMapEditor::_canvas_draw() {
if (mouse_over){
- const Vector2 endpoints[4]={
-
- xform.xform( over_tile * cell_size) ,
- xform.xform( (over_tile+Point2(1,0)) * cell_size) ,
- xform.xform( (over_tile+Point2(1,1)) * cell_size) ,
- xform.xform( (over_tile+Point2(0,1)) * cell_size) ,
+ Vector2 endpoints[4]={
+ ( node->map_to_world(over_tile,true) ) ,
+ ( node->map_to_world((over_tile+Point2(1,0)),true ) ),
+ ( node->map_to_world((over_tile+Point2(1,1)),true ) ),
+ ( node->map_to_world((over_tile+Point2(0,1)),true ) )
};
+
+ for(int i=0;i<4;i++) {
+ if (node->get_half_offset()==TileMap::HALF_OFFSET_X && ABS(over_tile.y)&1)
+ endpoints[i]+=cell_xf[0]*0.5;
+ if (node->get_half_offset()==TileMap::HALF_OFFSET_Y && ABS(over_tile.x)&1)
+ endpoints[i]+=cell_xf[1]*0.5;
+ endpoints[i]=xform.xform(endpoints[i]);
+ }
Color col;
if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
col=Color(0.2,0.8,1.0,0.8);
@@ -542,10 +608,10 @@ void TileMapEditor::_canvas_draw() {
Vector<Vector2> points;
- points.push_back( xform.xform( duplicate.pos * cell_size) );
- points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,0)) * cell_size) );
- points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1)) * cell_size) );
- points.push_back( xform.xform( (duplicate.pos+Point2(0,duplicate.size.y+1)) * cell_size) );
+ points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
+ points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
+ points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1))) ));
+ points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(0,duplicate.size.y+1))) ));
Color col=Color(0.2,1.0,0.8,0.4);
canvas_item_editor->draw_colored_polygon(points,col);
@@ -562,18 +628,19 @@ void TileMapEditor::_canvas_draw() {
Ref<Texture> t = ts->tile_get_texture(st);
if (t.is_valid()) {
- Rect2 r = ts->tile_get_region(st);
- Size2 sc = (endpoints[2]-endpoints[0])/cell_size;
+ Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+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;
if (r==Rect2()) {
- canvas_item_editor->draw_texture_rect(t,Rect2(endpoints[0],t->get_size()*sc),false,Color(1,1,1,0.5));
+ canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5));
} else {
- canvas_item_editor->draw_texture_rect_region(t,Rect2(endpoints[0],r.get_size()*sc),r,Color(1,1,1,0.5));
+ canvas_item_editor->draw_texture_rect_region(t,Rect2(from,r.get_size()*sc),r,Color(1,1,1,0.5));
}
}
}
@@ -633,23 +700,10 @@ 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);
@@ -663,36 +717,31 @@ 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 ));
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);
+ 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);
-
+ canvas_item_editor_hb->add_child(mirror_y);
+ canvas_item_editor_hb->hide();
tool=TOOL_NONE;
selection_active=false;
@@ -714,12 +763,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);
}
@@ -729,7 +778,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..ef869591bd 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;
@@ -63,7 +62,6 @@ class TileMapEditor : public HBoxContainer {
Panel *panel;
TileMap *node;
MenuButton *options;
- PaneDrag *pane_drag;
bool selection_active;
Point2i selection_begin;
@@ -75,6 +73,8 @@ class TileMapEditor : public HBoxContainer {
ToolButton *mirror_x;
ToolButton *mirror_y;
+ HBoxContainer *canvas_item_editor_hb;
+
struct CellOp {
int idx;
@@ -88,7 +88,6 @@ class TileMapEditor : public HBoxContainer {
int get_selected_tile() const;
void _update_palette();
- void _pane_drag(const Point2& p_to);
void _canvas_draw();
void _menu_option(int p_option);
@@ -99,14 +98,13 @@ class TileMapEditor : public HBoxContainer {
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();
public:
+ HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; }
Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_tile_map);
@@ -120,6 +118,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 6026cda4dc..a51caf7d54 100644
--- a/tools/editor/plugins/tile_set_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_set_editor_plugin.cpp
@@ -44,6 +44,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
Node *child = scene->get_child(i);
+
if (!child->cast_to<Sprite>()) {
if (child->get_child_count()>0) {
child=child->get_child(0);
@@ -72,7 +73,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
p_library->tile_set_texture(id,texture);
- Vector2 phys_offset = mi->get_offset();
+ Vector2 phys_offset;
if (mi->is_centered()) {
Size2 s;
@@ -112,7 +113,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
}
- p_library->tile_set_texture_offset(id,Vector2());
+ p_library->tile_set_texture_offset(id,mi->get_offset());
}
}
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 22331c86bf..449e54e12f 100644
--- a/tools/editor/project_export.cpp
+++ b/tools/editor/project_export.cpp
@@ -31,13 +31,13 @@
#include "os/dir_access.h"
#include "os/file_access.h"
#include "globals.h"
-#include "scene/io/scene_loader.h"
+
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "os/os.h"
#include "scene/gui/box_container.h"
#include "default_saver.h"
-#include "scene/io/scene_saver.h"
+
#include "scene/gui/tab_container.h"
#include "scene/gui/scroll_container.h"
#include "editor_data.h"
@@ -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..a600683097 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++;
@@ -970,9 +972,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) {
@@ -1863,11 +1867,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 +1880,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 +1994,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() {
@@ -2919,7 +2995,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 +3097,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/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..f5d9e83bf8 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -212,17 +212,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;
- if (next_pos< 0 || next_pos>=node->get_parent()->get_child_count())
- break; // invalid position
+ 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());
+
+ 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;
@@ -393,7 +426,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 +946,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 +957,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;
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 a23c9cead7..516cb5930d 100644
--- a/tools/editor/scenes_dock.cpp
+++ b/tools/editor/scenes_dock.cpp
@@ -30,7 +30,7 @@
#include "os/dir_access.h"
#include "os/file_access.h"
#include "globals.h"
-#include "scene/io/scene_loader.h"
+
#include "io/resource_loader.h"
#include "os/os.h"
#include "editor_node.h"
@@ -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: {
@@ -200,9 +200,11 @@ void ScenesDock::_instance_pressed() {
}
void ScenesDock::_open_pressed(){
+
TreeItem *sel = tree->get_selected();
- if (!sel)
+ if (!sel) {
return;
+ }
String path = sel->get_metadata(0);
if (ResourceLoader::get_resource_type(path)=="PackedScene") {
@@ -300,6 +302,7 @@ ScenesDock::ScenesDock(EditorNode *p_editor) {
tree->set_v_size_flags(SIZE_EXPAND_FILL);
tree->connect("item_edited",this,"_favorite_toggled");
+ tree->connect("item_activated",this,"_open_pressed");
timer = memnew( Timer );
timer->set_one_shot(true);
@@ -380,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 082878655c..d48a4ce813 100644
--- a/tools/editor/spatial_editor_gizmos.cpp
+++ b/tools/editor/spatial_editor_gizmos.cpp
@@ -36,7 +36,7 @@
#include "scene/resources/ray_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "scene/resources/plane_shape.h"
-#include "editor_shape_gizmos.h"
+#include "quick_hull.h"
// Keep small children away from this file.
// It's so ugly it will eat them alive
@@ -75,6 +75,7 @@ void SpatialGizmoTool::Instance::create_instance(Spatial *p_base) {
VS::get_singleton()->instance_set_extra_visibility_margin(instance,1);
VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_CAST_SHADOW,false);
VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_RECEIVE_SHADOWS,false);
+ VS::get_singleton()->instance_set_layer_mask(instance,1<<SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26
}
@@ -1237,6 +1238,10 @@ void SkeletonSpatialGizmo::redraw() {
weights[0]=1;
+ AABB aabb;
+
+ Color bonecolor = Color(1.0,0.4,0.4,0.3);
+ Color rootcolor = Color(0.4,1.0,0.4,0.1);
for (int i=0;i<skel->get_bone_count();i++) {
@@ -1247,8 +1252,96 @@ void SkeletonSpatialGizmo::redraw() {
Vector3 v0 = grests[parent].origin;
Vector3 v1 = grests[i].origin;
+ Vector3 d = (v1-v0).normalized();
+ float dist = v0.distance_to(v1);
+
+ //find closest axis
+ int closest=-1;
+ float closest_d;
+ for(int j=0;j<3;j++) {
+ float dp = Math::abs(grests[parent].basis[j].normalized().dot(d));
+ if (j==0 || dp>closest_d)
+ closest=j;
+ }
+
+ //find closest other
+ Vector3 first;
+ Vector3 points[4];
+ int pointidx=0;
+ for(int j=0;j<3;j++) {
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(rootcolor);
+ surface_tool->add_vertex(v0-grests[parent].basis[j].normalized()*dist*0.05);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(rootcolor);
+ surface_tool->add_vertex(v0+grests[parent].basis[j].normalized()*dist*0.05);
+
+ if (j==closest)
+ continue;
+
+ Vector3 axis;
+ if (first==Vector3()) {
+ axis = d.cross(d.cross(grests[parent].basis[j])).normalized();
+ first=axis;
+ } else {
+ axis = d.cross(first).normalized();
+ }
+
+ for(int k=0;k<2;k++) {
+
+ if (k==1)
+ axis=-axis;
+ Vector3 point = v0+d*dist*0.2;
+ point+=axis*dist*0.1;
+
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(v0);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(point);
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(point);
+ bones[0]=i;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(v1);
+ points[pointidx++]=point;
+
+ }
+
+ }
+
+ SWAP( points[1],points[2] );
+ for(int j=0;j<4;j++) {
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(points[j]);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(points[(j+1)%4]);
+ }
+
+
+/*
bones[0]=parent;
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
@@ -1259,13 +1352,13 @@ void SkeletonSpatialGizmo::redraw() {
surface_tool->add_weights(weights);
surface_tool->add_color(Color(0.4,1,0.4,0.4));
surface_tool->add_vertex(v1);
-
+*/
} else {
grests[i]=skel->get_bone_rest(i);
bones[0]=i;
}
-
+/*
Transform t = grests[i];
t.orthonormalize();
@@ -1302,6 +1395,7 @@ void SkeletonSpatialGizmo::redraw() {
}
}
+ */
}
Ref<Mesh> m = surface_tool->commit();
@@ -1474,69 +1568,6 @@ RayCastSpatialGizmo::RayCastSpatialGizmo(RayCast* p_raycast){
}
-/////
-
-
-void CarWheelSpatialGizmo::redraw() {
-
- clear();
-
-
- Vector<Vector3> points;
-
- float r = car_wheel->get_radius();
- const int skip=10;
- for(int i=0;i<=360;i+=skip) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+skip);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));
-
- const int springsec=4;
-
- for(int j=0;j<springsec;j++) {
- float t = car_wheel->get_travel()*5;
- points.push_back(Vector3(a.x,i/360.0*t/springsec+j*(t/springsec),a.y)*0.2);
- points.push_back(Vector3(b.x,(i+skip)/360.0*t/springsec+j*(t/springsec),b.y)*0.2);
- }
-
-
- }
-
- //travel
- points.push_back(Vector3(0,0,0));
- points.push_back(Vector3(0,car_wheel->get_travel(),0));
-
- //axis
- points.push_back(Vector3(r*0.2,car_wheel->get_travel(),0));
- points.push_back(Vector3(-r*0.2,car_wheel->get_travel(),0));
- //axis
- points.push_back(Vector3(r*0.2,0,0));
- points.push_back(Vector3(-r*0.2,0,0));
-
- //forward line
- points.push_back(Vector3(0,-r,0));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(r*2*0.2,-r,r*2*0.8));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(-r*2*0.2,-r,r*2*0.8));
-
- add_lines(points,SpatialEditorGizmos::singleton->car_wheel_material);
- add_collision_segments(points);
-
-}
-
-CarWheelSpatialGizmo::CarWheelSpatialGizmo(CarWheel* p_car_wheel){
-
- set_spatial_node(p_car_wheel);
- car_wheel=p_car_wheel;
-}
-
/////
@@ -1748,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)
@@ -2041,6 +2072,34 @@ void CollisionShapeSpatialGizmo::redraw(){
}
+ if (s->cast_to<ConvexPolygonShape>()) {
+
+ DVector<Vector3> points = s->cast_to<ConvexPolygonShape>()->get_points();
+
+ if (points.size()>3) {
+
+ QuickHull qh;
+ Vector<Vector3> varr = Variant(points);
+ Geometry::MeshData md;
+ Error err = qh.build(varr,md);
+ if (err==OK) {
+ Vector<Vector3> points;
+ points.resize(md.edges.size()*2);
+ for(int i=0;i<md.edges.size();i++) {
+ points[i*2+0]=md.vertices[md.edges[i].a];
+ points[i*2+1]=md.vertices[md.edges[i].b];
+ }
+
+
+ add_lines(points,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(points);
+
+ }
+ }
+
+ }
+
+
if (s->cast_to<RayShape>()) {
Ref<RayShape> rs=s;
@@ -2273,7 +2332,8 @@ void NavigationMeshSpatialGizmo::redraw() {
Ref<TriangleMesh> tmesh = memnew( TriangleMesh);
tmesh->create(tmeshfaces);
- add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
+ if (lines.size())
+ add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
add_collision_triangles(tmesh);
Ref<Mesh> m = memnew( Mesh );
Array a;
@@ -2888,16 +2948,6 @@ Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) {
return misg;
}
- if (p_spatial->cast_to<EditableShape>()) {
-
- Ref<EditableShapeSpatialGizmo> misg = memnew( EditableShapeSpatialGizmo(p_spatial->cast_to<EditableShape>()) );
- return misg;
- }
- if (p_spatial->cast_to<CarWheel>()) {
-
- Ref<CarWheelSpatialGizmo> misg = memnew( CarWheelSpatialGizmo(p_spatial->cast_to<CarWheel>()) );
- return misg;
- }
if (p_spatial->cast_to<VehicleWheel>()) {
Ref<VehicleWheelSpatialGizmo> misg = memnew( VehicleWheelSpatialGizmo(p_spatial->cast_to<VehicleWheel>()) );
diff --git a/tools/editor/spatial_editor_gizmos.h b/tools/editor/spatial_editor_gizmos.h
index 55e40c7b7c..7f39b648d7 100644
--- a/tools/editor/spatial_editor_gizmos.h
+++ b/tools/editor/spatial_editor_gizmos.h
@@ -44,7 +44,7 @@
#include "scene/3d/portal.h"
#include "scene/3d/ray_cast.h"
#include "scene/3d/navigation_mesh.h"
-#include "scene/3d/car_body.h"
+
#include "scene/3d/vehicle_body.h"
#include "scene/3d/collision_polygon.h"
#include "scene/3d/physics_joint.h"
@@ -332,19 +332,6 @@ public:
};
-class CarWheelSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(CarWheelSpatialGizmo,SpatialGizmoTool);
-
- CarWheel* car_wheel;
-
-public:
-
- void redraw();
- CarWheelSpatialGizmo(CarWheel* p_car_wheel=NULL);
-
-};
-
class VehicleWheelSpatialGizmo : public SpatialGizmoTool {
diff --git a/tools/export/blender25/godot_export_manager.py b/tools/export/blender25/godot_export_manager.py
new file mode 100644
index 0000000000..a5df60e47d
--- /dev/null
+++ b/tools/export/blender25/godot_export_manager.py
@@ -0,0 +1,439 @@
+# ##### 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_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."
+
+ 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." )
+ 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(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_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)
+
+ 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
+
+ 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
+
+ for i,object in enumerate(group[self.idx].nodes):
+
+ if object.name in bpy.data.objects:
+ 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
+
+ else: # if object is not in the scene anymore it will be removed from the group
+ group[self.idx].nodes.remove(i)
+ 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'})
+
+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.unlregister_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/install.txt b/tools/export/blender25/install.txt
index b245bbf3df..049af8848e 100644
--- a/tools/export/blender25/install.txt
+++ b/tools/export/blender25/install.txt
@@ -5,19 +5,7 @@ Godot Author's Own Collada Exporter
scripts/addons folder (You will see many other io_scene_blahblah like
folders). Copy the entire dir, not just the contents, make it just like
the others.
-2) Go to Blender settings and enable the "Khronos Collada" plugin
+2) Go to Blender settings and enable the "Better Collada" plugin
3) Enjoy proper Collada export.
-4) If it's broken, you can:
- a) Flame the Blender developers in their mailing list for changing
- the API every month.
- b) Flame the Blender developers for not giving a home to this script
- and mantaining it themselves, instead choosing to use the huge,
- bloated and buggy OpenCollada based implementation that is as big
- as Blender itself, while this script is a little over 1000 lines
- of code, works better and has more features.
- c) Cry to the poor Godot developers who are busy enough to fix it,
- because they are good people and will fix it for you anyway (submit
- an issue to github).
- d) Be a Hero, save the day, fix it yourself and submit a pull request to
- github with the changes.
+4) If it's broken, contact us.
\ No newline at end of file
diff --git a/tools/export/blender25/io_scene_dae/__init__.py b/tools/export/blender25/io_scene_dae/__init__.py
index fe8a383383..b3e3f70cf0 100644
--- a/tools/export/blender25/io_scene_dae/__init__.py
+++ b/tools/export/blender25/io_scene_dae/__init__.py
@@ -19,14 +19,14 @@
# <pep8-80 compliant>
bl_info = {
- "name": "Khronos Collada format",
+ "name": "Better Collada Exporter",
"author": "Juan Linietsky",
"blender": (2, 5, 8),
"api": 38691,
"location": "File > Import-Export",
- "description": ("Export DAE Scenes"),
+ "description": ("Export DAE Scenes, This plugin actually works better! otherwise contact me."),
"warning": "",
- "wiki_url": ("None"),
+ "wiki_url": ("http://www.godotengine.org"),
"tracker_url": "",
"support": 'OFFICIAL',
"category": "Import-Export"}
@@ -83,6 +83,17 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
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)",
@@ -108,11 +119,17 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
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 "
@@ -121,16 +138,13 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
soft_min=1, soft_max=16,
default=6.0,
)
+
use_metadata = BoolProperty(
name="Use Metadata",
default=True,
options={'HIDDEN'},
)
- export_shapekeys = BoolProperty(
- name="Export Shape Keys",
- default=False,
- )
-
+
@property
def check_extension(self):
return True#return self.batch_mode == 'OFF'
@@ -166,7 +180,7 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
def menu_func(self, context):
- self.layout.operator(ExportDAE.bl_idname, text="Khronos Collada (.dae)")
+ self.layout.operator(ExportDAE.bl_idname, text="Better Collada (.dae)")
def register():
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py
index 38c5c3b723..8161f05bf8 100644
--- a/tools/export/blender25/io_scene_dae/export_dae.py
+++ b/tools/export/blender25/io_scene_dae/export_dae.py
@@ -43,6 +43,7 @@ import time
import math # math.pi
import shutil
import bpy
+import bmesh
from mathutils import Vector, Matrix
#according to collada spec, order matters
@@ -51,12 +52,14 @@ S_IMGS=1
S_FX=2
S_MATS=3
S_GEOM=4
-S_CONT=5
-S_CAMS=6
-S_LAMPS=7
-S_ANIM_CLIPS=8
-S_NODES=9
-S_ANIM=10
+S_MORPH=5
+S_SKIN=6
+S_CONT=7
+S_CAMS=8
+S_LAMPS=9
+S_ANIM_CLIPS=10
+S_NODES=11
+S_ANIM=12
CMP_EPSILON=0.0001
@@ -123,12 +126,25 @@ class DaeExporter:
tup = (self.vertex.x,self.vertex.y,self.vertex.z,self.normal.x,self.normal.y,self.normal.z)
for t in self.uv:
tup = tup + (t.x,t.y)
+ if (self.color!=None):
+ tup = tup + (self.color.x,self.color.y,self.color.z)
+ if (self.tangent!=None):
+ 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)
+
return tup
def __init__(self):
self.vertex = Vector( (0.0,0.0,0.0) )
self.normal = Vector( (0.0,0.0,0.0) )
- self.color = Vector( (0.0,0.0,0.0) )
+ self.tangent = None
+ self.bitangent = None
+ self.color = None
self.uv = []
self.uv2 = Vector( (0.0,0.0) )
self.bones=[]
@@ -146,33 +162,61 @@ 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")
+
+ if (not os.path.isfile(imgpath)):
+ if img_tmp_path.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
+ imgpath="images/"+os.path.basename(img_tmp_path)
+ 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>')
@@ -281,9 +325,9 @@ class DaeExporter:
self.writel(S_FX,5,'</transparency>')
- self.writel(S_FX,5,'<index_of_refraction>'+str(material.specular_ior)+'</index_of_refraction>')
self.writel(S_FX,4,'</'+shtype+'>')
+ self.writel(S_FX,4,'<index_of_refraction>'+str(material.specular_ior)+'</index_of_refraction>')
self.writel(S_FX,4,'<extra>')
self.writel(S_FX,5,'<technique profile="FCOLLADA">')
@@ -315,15 +359,138 @@ class DaeExporter:
return matid
- def export_mesh(self,node,armature=None,shapename=None):
+ def export_mesh(self,node,armature=None,skeyindex=-1,skel_source=None,custom_name=None):
- if (node.data in self.mesh_cache) and shapename==None:
+ mesh = node.data
+
+
+ if (node.data in self.mesh_cache):
return self.mesh_cache[mesh]
- if (len(node.modifiers) and self.config["use_mesh_modifiers"]) or shapename!=None:
- mesh=node.to_mesh(self.scene,True,"RENDER") #is this allright?
- else:
- mesh=node.data
+ if (skeyindex==-1 and mesh.shape_keys!=None and len(mesh.shape_keys.key_blocks)):
+ values=[]
+ morph_targets=[]
+ md=None
+ for k in range(0,len(mesh.shape_keys.key_blocks)):
+ shape = node.data.shape_keys.key_blocks[k]
+ values+=[shape.value] #save value
+ shape.value=0
+
+ mid = self.new_id("morph")
+
+ for k in range(0,len(mesh.shape_keys.key_blocks)):
+
+ shape = node.data.shape_keys.key_blocks[k]
+ node.show_only_shape_key=True
+ node.active_shape_key_index = k
+ shape.value = 1.0
+ mesh.update()
+ """
+ oldval = shape.value
+ shape.value = 1.0
+
+ """
+ p = node.data
+ v = node.to_mesh(bpy.context.scene, True, "RENDER")
+ node.data = v
+# self.export_node(node,il,shape.name)
+ node.data.update()
+ if (armature and k==0):
+ md=self.export_mesh(node,armature,k,mid,shape.name)
+ else:
+ md=self.export_mesh(node,None,k,None,shape.name)
+
+ node.data = p
+ node.data.update()
+ shape.value = 0.0
+ morph_targets.append(md)
+
+ """
+ shape.value = oldval
+ """
+ node.show_only_shape_key=False
+ node.active_shape_key_index = 0
+
+
+ self.writel(S_MORPH,1,'<controller id="'+mid+'" name="">')
+ #if ("skin_id" in morph_targets[0]):
+ # self.writel(S_MORPH,2,'<morph source="#'+morph_targets[0]["skin_id"]+'" method="NORMALIZED">')
+ #else:
+ self.writel(S_MORPH,2,'<morph source="#'+morph_targets[0]["id"]+'" method="NORMALIZED">')
+
+ self.writel(S_MORPH,3,'<source id="'+mid+'-morph-targets">')
+ self.writel(S_MORPH,4,'<IDREF_array id="'+mid+'-morph-targets-array" count="'+str(len(morph_targets)-1)+'">')
+ marr=""
+ warr=""
+ for i in range(len(morph_targets)):
+ if (i==0):
+ continue
+ elif (i>1):
+ marr+=" "
+
+ if ("skin_id" in morph_targets[i]):
+ marr+=morph_targets[i]["skin_id"]
+ else:
+ marr+=morph_targets[i]["id"]
+
+ warr+=" 0"
+
+ self.writel(S_MORPH,5,marr)
+ self.writel(S_MORPH,4,'</IDREF_array>')
+ self.writel(S_MORPH,4,'<technique_common>')
+ self.writel(S_MORPH,5,'<accessor source="#'+mid+'-morph-targets-array" count="'+str(len(morph_targets)-1)+'" stride="1">')
+ self.writel(S_MORPH,6,'<param name="MORPH_TARGET" type="IDREF"/>')
+ self.writel(S_MORPH,5,'</accessor>')
+ self.writel(S_MORPH,4,'</technique_common>')
+ self.writel(S_MORPH,3,'</source>')
+
+ self.writel(S_MORPH,3,'<source id="'+mid+'-morph-weights">')
+ self.writel(S_MORPH,4,'<float_array id="'+mid+'-morph-weights-array" count="'+str(len(morph_targets)-1)+'" >')
+ self.writel(S_MORPH,5,warr)
+ self.writel(S_MORPH,4,'</float_array>')
+ self.writel(S_MORPH,4,'<technique_common>')
+ self.writel(S_MORPH,5,'<accessor source="#'+mid+'-morph-weights-array" count="'+str(len(morph_targets)-1)+'" stride="1">')
+ self.writel(S_MORPH,6,'<param name="MORPH_WEIGHT" type="float"/>')
+ self.writel(S_MORPH,5,'</accessor>')
+ self.writel(S_MORPH,4,'</technique_common>')
+ self.writel(S_MORPH,3,'</source>')
+
+ self.writel(S_MORPH,3,'<targets>')
+ self.writel(S_MORPH,4,'<input semantic="MORPH_TARGET" source="#'+mid+'-morph-targets"/>')
+ self.writel(S_MORPH,4,'<input semantic="MORPH_WEIGHT" source="#'+mid+'-morph-weights"/>')
+ self.writel(S_MORPH,3,'</targets>')
+ self.writel(S_MORPH,2,'</morph>')
+ self.writel(S_MORPH,1,'</controller>')
+ if (armature!=None):
+
+ self.armature_for_morph[node]=armature
+
+ meshdata={}
+ if (armature):
+ meshdata = morph_targets[0]
+ meshdata["morph_id"]=mid
+ else:
+ meshdata["id"]=morph_targets[0]["id"]
+ meshdata["morph_id"]=mid
+ meshdata["material_assign"]=morph_targets[0]["material_assign"]
+
+
+
+ self.mesh_cache[node.data]=meshdata
+ return meshdata
+
+ apply_modifiers = len(node.modifiers) and self.config["use_mesh_modifiers"]
+
+ mesh=node.to_mesh(self.scene,apply_modifiers,"RENDER") #is this allright?
+
+ triangulate=self.config["use_triangles"]
+ if (triangulate):
+ bm = bmesh.new()
+ bm.from_mesh(mesh)
+ bmesh.ops.triangulate(bm, faces=bm.faces)
+ bm.to_mesh(mesh)
+ bm.free()
+
mesh.update(calc_tessface=True)
vertices=[]
@@ -340,21 +507,33 @@ class DaeExporter:
has_uv=False
has_uv2=False
has_weights=armature!=None
- has_colors=False
+ has_tangents=self.config["use_tangent_arrays"] # could detect..
+ has_colors=len(mesh.vertex_colors)
mat_assign=[]
uv_layer_count=len(mesh.uv_textures)
+ if (len(mesh.uv_textures)):
+ try:
+ mesh.calc_tangents()
+ except:
+ print("Warning, blender API is fucked up, not exporting UVs for this object.")
+ 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.tessfaces)):
- f=mesh.tessfaces[fi]
+ for fi in range(len(mesh.polygons)):
+ f=mesh.polygons[fi]
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)))
-
try:
#Bizarre blender behavior i don't understand, so catching exception
mat = mesh.materials[f.material_index]
@@ -368,35 +547,42 @@ class DaeExporter:
indices = surface_indices[f.material_index]
vi=[]
- #make triangles always
+ #vertices always 3
+ """
if (len(f.vertices)==3):
vi.append(0)
vi.append(1)
vi.append(2)
elif (len(f.vertices)==4):
+ #todo, should use shortest path
vi.append(0)
vi.append(1)
vi.append(2)
vi.append(0)
vi.append(2)
vi.append(3)
+ """
- for x in vi:
- mv = mesh.vertices[f.vertices[x]]
+ for lt in range(f.loop_total):
+ loop_index = f.loop_start + lt
+ ml = mesh.loops[loop_index]
+ mv = mesh.vertices[ml.vertex_index]
v = self.Vertex()
v.vertex = Vector( mv.co )
- for xt in mesh.tessface_uv_textures:
- d = xt.data[fi]
- uvsrc = [d.uv1,d.uv2,d.uv3,d.uv4]
- v.uv.append( Vector( uvsrc[x] ) )
+ for xt in mesh.uv_layers:
+ v.uv.append( Vector( xt.data[loop_index].uv ) )
+ if (has_colors):
+ v.color = Vector( mesh.vertex_colors[0].data[loop_index].color )
+
+ v.normal = Vector( ml.normal )
+
+ if (has_tangents):
+ v.tangent = Vector( ml.tangent )
+ v.bitangent = Vector( ml.bitangent )
- if (f.use_smooth):
- v.normal=Vector( mv.normal )
- else:
- v.normal=Vector( f.normal )
# if (armature):
# v.vertex = node.matrix_world * v.vertex
@@ -410,6 +596,7 @@ class DaeExporter:
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)
@@ -418,20 +605,24 @@ class DaeExporter:
tup = v.get_tup()
idx = 0
- if (tup in vertex_map):
+ if (skeyindex==-1 and tup in vertex_map): #do not optmize if using shapekeys
idx = vertex_map[tup]
else:
idx = len(vertices)
vertices.append(v)
vertex_map[tup]=idx
- indices.append(idx)
+ vi.append(idx)
+
+ if (len(vi)>2):
+ #only triangles and above
+ indices.append(vi)
+
- if shapename != None:
- meshid = self.new_id("mesh_"+shapename)
- self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'_'+shapename+'">')
+ meshid = self.new_id("mesh")
+ if (custom_name!=None):
+ self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+custom_name+'">')
else:
- meshid = self.new_id("mesh")
self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">')
self.writel(S_GEOM,2,'<mesh>')
@@ -468,6 +659,37 @@ class DaeExporter:
self.writel(S_GEOM,4,'</technique_common>')
self.writel(S_GEOM,3,'</source>')
+ if (has_tangents):
+ self.writel(S_GEOM,3,'<source id="'+meshid+'-tangents">')
+ float_values=""
+ for v in vertices:
+ float_values+=" "+str(v.tangent.x)+" "+str(v.tangent.y)+" "+str(v.tangent.z)
+ self.writel(S_GEOM,4,'<float_array id="'+meshid+'-tangents-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>')
+ self.writel(S_GEOM,4,'<technique_common>')
+ self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-tangents-array" count="'+str(len(vertices))+'" stride="3">')
+ self.writel(S_GEOM,5,'<param name="X" type="float"/>')
+ self.writel(S_GEOM,5,'<param name="Y" type="float"/>')
+ self.writel(S_GEOM,5,'<param name="Z" type="float"/>')
+ self.writel(S_GEOM,4,'</accessor>')
+ self.writel(S_GEOM,4,'</technique_common>')
+ self.writel(S_GEOM,3,'</source>')
+
+ self.writel(S_GEOM,3,'<source id="'+meshid+'-bitangents">')
+ float_values=""
+ for v in vertices:
+ float_values+=" "+str(v.bitangent.x)+" "+str(v.bitangent.y)+" "+str(v.bitangent.z)
+ self.writel(S_GEOM,4,'<float_array id="'+meshid+'-bitangents-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>')
+ self.writel(S_GEOM,4,'<technique_common>')
+ self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-bitangents-array" count="'+str(len(vertices))+'" stride="3">')
+ self.writel(S_GEOM,5,'<param name="X" type="float"/>')
+ self.writel(S_GEOM,5,'<param name="Y" type="float"/>')
+ self.writel(S_GEOM,5,'<param name="Z" type="float"/>')
+ self.writel(S_GEOM,4,'</accessor>')
+ self.writel(S_GEOM,4,'</technique_common>')
+ self.writel(S_GEOM,3,'</source>')
+
+
+
# UV Arrays
for uvi in range(uv_layer_count):
@@ -475,7 +697,12 @@ class DaeExporter:
self.writel(S_GEOM,3,'<source id="'+meshid+'-texcoord-'+str(uvi)+'">')
float_values=""
for v in vertices:
- float_values+=" "+str(v.uv[uvi].x)+" "+str(v.uv[uvi].y)
+ try:
+ float_values+=" "+str(v.uv[uvi].x)+" "+str(v.uv[uvi].y)
+ except:
+ # I don't understand this weird multi-uv-layer API, but with this it seems to works
+ float_values+=" 0 0 "
+
self.writel(S_GEOM,4,'<float_array id="'+meshid+'-texcoord-'+str(uvi)+'-array" count="'+str(len(vertices)*2)+'">'+float_values+'</float_array>')
self.writel(S_GEOM,4,'<technique_common>')
self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-texcoord-'+str(uvi)+'-array" count="'+str(len(vertices))+'" stride="2">')
@@ -485,84 +712,129 @@ class DaeExporter:
self.writel(S_GEOM,4,'</technique_common>')
self.writel(S_GEOM,3,'</source>')
+ # Color Arrays
+
+ if (has_colors):
+ self.writel(S_GEOM,3,'<source id="'+meshid+'-colors">')
+ float_values=""
+ for v in vertices:
+ float_values+=" "+str(v.color.x)+" "+str(v.color.y)+" "+str(v.color.z)
+ self.writel(S_GEOM,4,'<float_array id="'+meshid+'-colors-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>')
+ self.writel(S_GEOM,4,'<technique_common>')
+ self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-colors-array" count="'+str(len(vertices))+'" stride="3">')
+ self.writel(S_GEOM,5,'<param name="X" type="float"/>')
+ self.writel(S_GEOM,5,'<param name="Y" type="float"/>')
+ self.writel(S_GEOM,5,'<param name="Z" type="float"/>')
+ self.writel(S_GEOM,4,'</accessor>')
+ self.writel(S_GEOM,4,'</technique_common>')
+ self.writel(S_GEOM,3,'</source>')
+
# Triangle Lists
self.writel(S_GEOM,3,'<vertices id="'+meshid+'-vertices">')
self.writel(S_GEOM,4,'<input semantic="POSITION" source="#'+meshid+'-positions"/>')
self.writel(S_GEOM,3,'</vertices>')
+ prim_type=""
+ if (triangulate):
+ prim_type="triangles"
+ else:
+ prim_type="polygons"
+
+
for m in surface_indices:
indices = surface_indices[m]
mat = materials[m]
+
if (mat!=None):
matref = self.new_id("trimat")
- self.writel(S_GEOM,3,'<triangles count="'+str(int(len(indices)/3))+'" material="'+matref+'">') # todo material
+ self.writel(S_GEOM,3,'<'+prim_type+' count="'+str(int(len(indices)))+'" material="'+matref+'">') # todo material
mat_assign.append( (mat,matref) )
else:
- self.writel(S_GEOM,3,'<triangles count="'+str(int(len(indices)/3))+'">') # todo material
+ self.writel(S_GEOM,3,'<'+prim_type+' count="'+str(int(len(indices)))+'">') # todo material
+
+
self.writel(S_GEOM,4,'<input semantic="VERTEX" source="#'+meshid+'-vertices" offset="0"/>')
- self.writel(S_GEOM,4,'<input semantic="NORMAL" source="#'+meshid+'-normals" offset="1"/>')
- extra_indices=0
+ self.writel(S_GEOM,4,'<input semantic="NORMAL" source="#'+meshid+'-normals" offset="0"/>')
+
for uvi in range(uv_layer_count):
- self.writel(S_GEOM,4,'<input semantic="TEXCOORD" source="#'+meshid+'-texcoord-'+str(uvi)+'" offset="'+str(2+uvi)+'" set="'+str(uvi)+'"/>')
- extra_indices+=1
+ self.writel(S_GEOM,4,'<input semantic="TEXCOORD" source="#'+meshid+'-texcoord-'+str(uvi)+'" offset="0" set="'+str(uvi)+'"/>')
+
+ if (has_colors):
+ self.writel(S_GEOM,4,'<input semantic="COLOR" source="#'+meshid+'-colors" offset="0"/>')
+ if (has_tangents):
+ self.writel(S_GEOM,4,'<input semantic="TEXTANGENT" source="#'+meshid+'-tangents" offset="0"/>')
+ self.writel(S_GEOM,4,'<input semantic="TEXBINORMAL" source="#'+meshid+'-bitangents" offset="0"/>')
+
+ if (triangulate):
+ int_values="<p>"
+ for p in indices:
+ for i in p:
+ int_values+=" "+str(i)
+ int_values+=" </p>"
+ self.writel(S_GEOM,4,int_values)
+ else:
+ for p in indices:
+ int_values="<p>"
+ for i in p:
+ int_values+=" "+str(i)
+ int_values+=" </p>"
+ self.writel(S_GEOM,4,int_values)
- int_values="<p>"
- for i in range(len(indices)):
- int_values+=" "+str(indices[i]) # vertex index
- int_values+=" "+str(indices[i]) # normal index
- for e in range(extra_indices):
- int_values+=" "+str(indices[i]) # normal index
- int_values+="</p>"
- self.writel(S_GEOM,4,int_values)
- self.writel(S_GEOM,3,'</triangles>')
+ self.writel(S_GEOM,3,'</'+prim_type+'>')
self.writel(S_GEOM,2,'</mesh>')
self.writel(S_GEOM,1,'</geometry>')
+
meshdata={}
meshdata["id"]=meshid
meshdata["material_assign"]=mat_assign
- self.mesh_cache[node.data]=meshdata
+ if (skeyindex==-1):
+ self.mesh_cache[node.data]=meshdata
# Export armature data (if armature exists)
- if (armature!=None):
+ if (armature!=None and (skel_source!=None or skeyindex==-1)):
contid = self.new_id("controller")
- self.writel(S_CONT,1,'<controller id="'+contid+'">')
- self.writel(S_CONT,2,'<skin source="'+meshid+'">')
- self.writel(S_CONT,3,'<bind_shape_matrix>'+strmtx(node.matrix_world)+'</bind_shape_matrix>')
+ self.writel(S_SKIN,1,'<controller id="'+contid+'">')
+ if (skel_source!=None):
+ self.writel(S_SKIN,2,'<skin source="#'+skel_source+'">')
+ else:
+ self.writel(S_SKIN,2,'<skin source="#'+meshid+'">')
+
+ self.writel(S_SKIN,3,'<bind_shape_matrix>'+strmtx(node.matrix_world)+'</bind_shape_matrix>')
#Joint Names
- self.writel(S_CONT,3,'<source id="'+contid+'-joints">')
+ self.writel(S_SKIN,3,'<source id="'+contid+'-joints">')
name_values=""
for v in si["bone_names"]:
name_values+=" "+v
- self.writel(S_CONT,4,'<Name_array id="'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'">'+name_values+'</Name_array>')
- self.writel(S_CONT,4,'<technique_common>')
- self.writel(S_CONT,4,'<accessor source="#'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'" stride="1">')
- self.writel(S_CONT,5,'<param name="JOINT" type="Name"/>')
- self.writel(S_CONT,4,'</accessor>')
- self.writel(S_CONT,4,'</technique_common>')
- self.writel(S_CONT,3,'</source>')
+ self.writel(S_SKIN,4,'<Name_array id="'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'">'+name_values+'</Name_array>')
+ self.writel(S_SKIN,4,'<technique_common>')
+ self.writel(S_SKIN,4,'<accessor source="#'+contid+'-joints-array" count="'+str(len(si["bone_names"]))+'" stride="1">')
+ self.writel(S_SKIN,5,'<param name="JOINT" type="Name"/>')
+ self.writel(S_SKIN,4,'</accessor>')
+ self.writel(S_SKIN,4,'</technique_common>')
+ self.writel(S_SKIN,3,'</source>')
#Pose Matrices!
- self.writel(S_CONT,3,'<source id="'+contid+'-bind_poses">')
+ self.writel(S_SKIN,3,'<source id="'+contid+'-bind_poses">')
pose_values=""
for v in si["bone_bind_poses"]:
pose_values+=" "+strmtx(v)
- self.writel(S_CONT,4,'<float_array id="'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"])*16)+'">'+pose_values+'</float_array>')
- self.writel(S_CONT,4,'<technique_common>')
- self.writel(S_CONT,4,'<accessor source="#'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"]))+'" stride="16">')
- self.writel(S_CONT,5,'<param name="TRANSFORM" type="float4x4"/>')
- self.writel(S_CONT,4,'</accessor>')
- self.writel(S_CONT,4,'</technique_common>')
- self.writel(S_CONT,3,'</source>')
+ self.writel(S_SKIN,4,'<float_array id="'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"])*16)+'">'+pose_values+'</float_array>')
+ self.writel(S_SKIN,4,'<technique_common>')
+ self.writel(S_SKIN,4,'<accessor source="#'+contid+'-bind_poses-array" count="'+str(len(si["bone_bind_poses"]))+'" stride="16">')
+ self.writel(S_SKIN,5,'<param name="TRANSFORM" type="float4x4"/>')
+ self.writel(S_SKIN,4,'</accessor>')
+ self.writel(S_SKIN,4,'</technique_common>')
+ self.writel(S_SKIN,3,'</source>')
#Skin Weights!
- self.writel(S_CONT,3,'<source id="'+contid+'-skin_weights">')
+ self.writel(S_SKIN,3,'<source id="'+contid+'-skin_weights">')
skin_weights=""
skin_weights_total=0
for v in vertices:
@@ -570,22 +842,22 @@ class DaeExporter:
for w in v.weights:
skin_weights+=" "+str(w)
- self.writel(S_CONT,4,'<float_array id="'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'">'+skin_weights+'</float_array>')
- self.writel(S_CONT,4,'<technique_common>')
- self.writel(S_CONT,4,'<accessor source="#'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'" stride="1">')
- self.writel(S_CONT,5,'<param name="WEIGHT" type="float"/>')
- self.writel(S_CONT,4,'</accessor>')
- self.writel(S_CONT,4,'</technique_common>')
- self.writel(S_CONT,3,'</source>')
-
-
- self.writel(S_CONT,3,'<joints>')
- self.writel(S_CONT,4,'<input semantic="JOINT" source="#'+contid+'-joints"/>')
- self.writel(S_CONT,4,'<input semantic="INV_BIND_MATRIX" source="#'+contid+'-bind_poses"/>')
- self.writel(S_CONT,3,'</joints>')
- self.writel(S_CONT,3,'<vertex_weights count="'+str(len(vertices))+'">')
- self.writel(S_CONT,4,'<input semantic="JOINT" source="#'+contid+'-joints" offset="0"/>')
- self.writel(S_CONT,4,'<input semantic="WEIGHT" source="#'+contid+'-skin_weights" offset="1"/>')
+ self.writel(S_SKIN,4,'<float_array id="'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'">'+skin_weights+'</float_array>')
+ self.writel(S_SKIN,4,'<technique_common>')
+ self.writel(S_SKIN,4,'<accessor source="#'+contid+'-skin_weights-array" count="'+str(skin_weights_total)+'" stride="1">')
+ self.writel(S_SKIN,5,'<param name="WEIGHT" type="float"/>')
+ self.writel(S_SKIN,4,'</accessor>')
+ self.writel(S_SKIN,4,'</technique_common>')
+ self.writel(S_SKIN,3,'</source>')
+
+
+ self.writel(S_SKIN,3,'<joints>')
+ self.writel(S_SKIN,4,'<input semantic="JOINT" source="#'+contid+'-joints"/>')
+ self.writel(S_SKIN,4,'<input semantic="INV_BIND_MATRIX" source="#'+contid+'-bind_poses"/>')
+ self.writel(S_SKIN,3,'</joints>')
+ self.writel(S_SKIN,3,'<vertex_weights count="'+str(len(vertices))+'">')
+ self.writel(S_SKIN,4,'<input semantic="JOINT" source="#'+contid+'-joints" offset="0"/>')
+ self.writel(S_SKIN,4,'<input semantic="WEIGHT" source="#'+contid+'-skin_weights" offset="1"/>')
vcounts=""
vs=""
vcount=0
@@ -595,20 +867,20 @@ class DaeExporter:
vs+=" "+str(b)
vs+=" "+str(vcount)
vcount+=1
- self.writel(S_CONT,4,'<vcount>'+vcounts+'</vcount>')
- self.writel(S_CONT,4,'<v>'+vs+'</v>')
- self.writel(S_CONT,3,'</vertex_weights>')
+ self.writel(S_SKIN,4,'<vcount>'+vcounts+'</vcount>')
+ self.writel(S_SKIN,4,'<v>'+vs+'</v>')
+ self.writel(S_SKIN,3,'</vertex_weights>')
- self.writel(S_CONT,2,'</skin>')
- self.writel(S_CONT,1,'</controller>')
+ self.writel(S_SKIN,2,'</skin>')
+ self.writel(S_SKIN,1,'</controller>')
meshdata["skin_id"]=contid
return meshdata
- def export_mesh_node(self,node,il,shapename=None):
+ def export_mesh_node(self,node,il):
if (node.data==None):
return
@@ -618,14 +890,33 @@ class DaeExporter:
if (node.parent.type=="ARMATURE"):
armature=node.parent
- meshdata = self.export_mesh(node,armature,shapename)
-
- if (armature==None):
- self.writel(S_NODES,il,'<instance_geometry url="#'+meshdata["id"]+'">')
- else:
+ 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
+
+ if ("skin_id" in meshdata):
+ close_controller=True
self.writel(S_NODES,il,'<instance_controller url="#'+meshdata["skin_id"]+'">')
for sn in self.skeleton_info[armature]["skeleton_nodes"]:
self.writel(S_NODES,il+1,'<skeleton>#'+sn+'</skeleton>')
+ elif ("morph_id" in meshdata):
+ self.writel(S_NODES,il,'<instance_controller url="#'+meshdata["morph_id"]+'">')
+ close_controller=True
+ elif (armature==None):
+ self.writel(S_NODES,il,'<instance_geometry url="#'+meshdata["id"]+'">')
if (len(meshdata["material_assign"])>0):
@@ -638,17 +929,17 @@ class DaeExporter:
self.writel(S_NODES,il+2,'</technique_common>')
self.writel(S_NODES,il+1,'</bind_material>')
- if (armature==None):
- self.writel(S_NODES,il,'</instance_geometry>')
- else:
+ if (close_controller):
self.writel(S_NODES,il,'</instance_controller>')
+ else:
+ self.writel(S_NODES,il,'</instance_geometry>')
def export_armature_bone(self,bone,il,si):
boneid = self.new_id("bone")
boneidx = si["bone_count"]
si["bone_count"]+=1
- bonesid = si["name"]+"-"+str(boneidx)
+ bonesid = si["id"]+"-"+str(boneidx)
si["bone_index"][bone.name]=boneidx
si["bone_ids"][bone]=boneid
si["bone_names"].append(bonesid)
@@ -677,7 +968,7 @@ class DaeExporter:
self.skeletons.append(node)
armature = node.data
- self.skeleton_info[node]={ "bone_count":0, "name":node.name, "bone_index":{},"bone_ids":{},"bone_names":[],"bone_bind_poses":[],"skeleton_nodes":[],"armature_xform":node.matrix_world }
+ self.skeleton_info[node]={ "bone_count":0, "id":self.new_id("skelbones"),"name":node.name, "bone_index":{},"bone_ids":{},"bone_names":[],"bone_bind_poses":[],"skeleton_nodes":[],"armature_xform":node.matrix_world }
@@ -733,7 +1024,7 @@ class DaeExporter:
light=node.data
lightid=self.new_id("light")
self.writel(S_LAMPS,1,'<light id="'+lightid+'" name="'+light.name+'">')
- self.writel(S_LAMPS,2,'<optics>')
+ #self.writel(S_LAMPS,2,'<optics>')
self.writel(S_LAMPS,3,'<technique_common>')
if (light.type=="POINT"):
@@ -761,7 +1052,7 @@ class DaeExporter:
self.writel(S_LAMPS,3,'</technique_common>')
- self.writel(S_LAMPS,2,'</optics>')
+ #self.writel(S_LAMPS,2,'</optics>')
self.writel(S_LAMPS,1,'</light>')
@@ -906,21 +1197,19 @@ class DaeExporter:
- def export_node(self,node,il,shapename=None):
- if (not self.is_node_valid(node)):
+ def export_node(self,node,il):
+ if (not node in self.valid_nodes):
return
+ prev_node = bpy.context.scene.objects.active
bpy.context.scene.objects.active = node
- if shapename != None:
- self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name + '_' + shapename)+'" name="'+node.name+'_'+shapename+'" type="NODE">')
- else:
- self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name)+'" name="'+node.name+'" type="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)
if (node.type=="MESH"):
- self.export_mesh_node(node,il,shapename)
+ self.export_mesh_node(node,il)
elif (node.type=="CURVE"):
self.export_curve_node(node,il)
elif (node.type=="ARMATURE"):
@@ -930,31 +1219,19 @@ class DaeExporter:
elif (node.type=="LAMP"):
self.export_lamp_node(node,il)
- self.valid_nodes.append(node)
- if shapename==None:
- for x in node.children:
- self.export_node(x,il)
- if node.type=="MESH" and self.config["export_shapekeys"]:
- for k in range(0,len(node.data.shape_keys.key_blocks)):
- shape = node.data.shape_keys.key_blocks[k]
- oldval = shape.value
- shape.value = 1.0
- node.active_shape_key_index = k
- p = node.data
- v = node.to_mesh(bpy.context.scene, True, "RENDER")
- node.data = v
- self.export_node(node,il,shape.name)
- node.data = p
- node.data.update()
- shape.value = oldval
+ 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
@@ -974,8 +1251,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>')
@@ -997,18 +1287,22 @@ class DaeExporter:
self.writel(S_ASSET,0,'</asset>')
- def export_animation_transform_channel(self,target,transform_keys):
+ def export_animation_transform_channel(self,target,keys,matrices=True):
- frame_total=len(transform_keys)
+ frame_total=len(keys)
anim_id=self.new_id("anim")
self.writel(S_ANIM,1,'<animation id="'+anim_id+'">')
source_frames = ""
source_transforms = ""
source_interps = ""
- for k in transform_keys:
+ for k in keys:
source_frames += " "+str(k[0])
- source_transforms += " "+strmtx(k[1])
+ if (matrices):
+ source_transforms += " "+strmtx(k[1])
+ else:
+ source_transforms += " "+str(k[1])
+
source_interps +=" LINEAR"
@@ -1016,27 +1310,38 @@ class DaeExporter:
self.writel(S_ANIM,2,'<source id="'+anim_id+'-input">')
self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-input-array" count="'+str(frame_total)+'">'+source_frames+'</float_array>')
self.writel(S_ANIM,3,'<technique_common>')
- self.writel(S_ANIM,4,'<accessor source="'+anim_id+'-input-array" count="'+str(frame_total)+'" stride="1">')
+ self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-input-array" count="'+str(frame_total)+'" stride="1">')
self.writel(S_ANIM,5,'<param name="TIME" type="float"/>')
self.writel(S_ANIM,4,'</accessor>')
self.writel(S_ANIM,3,'</technique_common>')
self.writel(S_ANIM,2,'</source>')
- # Transform Source
- self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">')
- self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total*16)+'">'+source_transforms+'</float_array>')
- self.writel(S_ANIM,3,'<technique_common>')
- self.writel(S_ANIM,4,'<accessor source="'+anim_id+'-transform-output-array" count="'+str(frame_total)+'" stride="16">')
- self.writel(S_ANIM,5,'<param name="TRANSFORM" type="float4x4"/>')
- self.writel(S_ANIM,4,'</accessor>')
- self.writel(S_ANIM,3,'</technique_common>')
- self.writel(S_ANIM,2,'</source>')
+ if (matrices):
+ # Transform Source
+ self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">')
+ self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total*16)+'">'+source_transforms+'</float_array>')
+ self.writel(S_ANIM,3,'<technique_common>')
+ self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-transform-output-array" count="'+str(frame_total)+'" stride="16">')
+ self.writel(S_ANIM,5,'<param name="TRANSFORM" type="float4x4"/>')
+ self.writel(S_ANIM,4,'</accessor>')
+ self.writel(S_ANIM,3,'</technique_common>')
+ self.writel(S_ANIM,2,'</source>')
+ else:
+ # Value Source
+ self.writel(S_ANIM,2,'<source id="'+anim_id+'-transform-output">')
+ self.writel(S_ANIM,3,'<float_array id="'+anim_id+'-transform-output-array" count="'+str(frame_total)+'">'+source_transforms+'</float_array>')
+ self.writel(S_ANIM,3,'<technique_common>')
+ self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-transform-output-array" count="'+str(frame_total)+'" stride="1">')
+ self.writel(S_ANIM,5,'<param name="X" type="float"/>')
+ self.writel(S_ANIM,4,'</accessor>')
+ self.writel(S_ANIM,3,'</technique_common>')
+ self.writel(S_ANIM,2,'</source>')
# Interpolation Source
self.writel(S_ANIM,2,'<source id="'+anim_id+'-interpolation-output">')
self.writel(S_ANIM,3,'<Name_array id="'+anim_id+'-interpolation-output-array" count="'+str(frame_total)+'">'+source_interps+'</Name_array>')
self.writel(S_ANIM,3,'<technique_common>')
- self.writel(S_ANIM,4,'<accessor source="'+anim_id+'-interpolation-output-array" count="'+str(frame_total)+'" stride="1">')
+ self.writel(S_ANIM,4,'<accessor source="#'+anim_id+'-interpolation-output-array" count="'+str(frame_total)+'" stride="1">')
self.writel(S_ANIM,5,'<param name="INTERPOLATION" type="Name"/>')
self.writel(S_ANIM,4,'</accessor>')
self.writel(S_ANIM,3,'</technique_common>')
@@ -1047,7 +1352,10 @@ class DaeExporter:
self.writel(S_ANIM,3,'<input semantic="OUTPUT" source="#'+anim_id+'-transform-output"/>')
self.writel(S_ANIM,3,'<input semantic="INTERPOLATION" source="#'+anim_id+'-interpolation-output"/>')
self.writel(S_ANIM,2,'</sampler>')
- self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'/transform"/>')
+ if (matrices):
+ self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'/transform"/>')
+ else:
+ self.writel(S_ANIM,2,'<channel source="#'+anim_id+'-sampler" target="'+target+'"/>')
self.writel(S_ANIM,1,'</animation>')
return [anim_id]
@@ -1059,6 +1367,8 @@ class DaeExporter:
#Collada starts from 0, blender usually from 1
#The last frame must be included also
+ frame_orig = self.scene.frame_current
+
frame_len = 1.0 / self.scene.render.fps
frame_total = end - start + 1
frame_sub = 0
@@ -1067,6 +1377,7 @@ class DaeExporter:
tcn = []
xform_cache={}
+ blend_cache={}
# Change frames first, export objects last
# This improves performance enormously
@@ -1081,9 +1392,27 @@ class DaeExporter:
if (not node in self.valid_nodes):
continue
if (allowed!=None and not (node in allowed)):
- continue
+ 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"]
+ for i in range(len(node.data.shape_keys.key_blocks)):
+
+ if (i==0):
+ continue
+
+ name=target+"-morph-weights("+str(i-1)+")"
+ if (not (name in blend_cache)):
+ blend_cache[name]=[]
+
+ blend_cache[name].append( (key,node.data.shape_keys.key_blocks[i].value) )
+
if (node.type=="MESH" and node.parent and node.parent.type=="ARMATURE"):
+
continue #In Collada, nodes that have skin modifier must not export animation, animate the skin instead.
if (len(node.constraints)>0 or node.animation_data!=None):
@@ -1100,6 +1429,7 @@ class DaeExporter:
if (node.type=="ARMATURE"):
#All bones exported for now
+
for bone in node.data.bones:
bone_name=self.skeleton_info[node]["bone_ids"][bone]
@@ -1126,25 +1456,43 @@ class DaeExporter:
xform_cache[bone_name].append( (key,mtx) )
+ self.scene.frame_set(frame_orig)
#export animation xml
for nid in xform_cache:
- tcn+=self.export_animation_transform_channel(nid,xform_cache[nid])
+ tcn+=self.export_animation_transform_channel(nid,xform_cache[nid],True)
+ for nid in blend_cache:
+ tcn+=self.export_animation_transform_channel(nid,blend_cache[nid],False)
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 = {}
+
+ for s in self.skeletons:
+ if s.animation_data and s.animation_data.action:
+ cached_actions[s] = s.animation_data.action.name
+
+
self.writel(S_ANIM_CLIPS,0,'<library_animation_clips>')
for x in bpy.data.actions[:]:
- if x in self.action_constraints:
+ if x.users==0 or x in self.action_constraints:
+ continue
+ if (self.config["use_anim_skip_noexp"] and x.name.endswith("-noexp")):
continue
bones=[]
@@ -1160,34 +1508,50 @@ 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))
- 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)
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,2,'<instance_animation url="#'+z+'"/>')
self.writel(S_ANIM_CLIPS,1,'</animation_clip>')
self.writel(S_ANIM_CLIPS,0,'</library_animation_clips>')
+ 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):
@@ -1207,6 +1571,19 @@ class DaeExporter:
self.export_scene()
self.writel(S_GEOM,0,'</library_geometries>')
+
+ #morphs always go before skin controllers
+ if S_MORPH in self.sections:
+ for l in self.sections[S_MORPH]:
+ self.writel(S_CONT,0,l)
+ del self.sections[S_MORPH]
+
+ #morphs always go before skin controllers
+ if S_SKIN in self.sections:
+ for l in self.sections[S_SKIN]:
+ self.writel(S_CONT,0,l)
+ del self.sections[S_SKIN]
+
self.writel(S_CONT,0,'</library_controllers>')
self.writel(S_CAMS,0,'</library_cameras>')
self.writel(S_LAMPS,0,'</library_lights>')
@@ -1253,6 +1630,8 @@ class DaeExporter:
self.skeleton_info={}
self.config=kwargs
self.valid_nodes=[]
+ self.armature_for_morph={}
+
diff --git a/version.py b/version.py
index 31257304f6..86601a22f2 100644
--- a/version.py
+++ b/version.py
@@ -2,7 +2,6 @@ short_name="godot"
name="Godot Engine"
major=1
minor=0
-revision="$Rev: 3917 $"
-status="beta1"
+status="stable"