summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--SConstruct141
-rw-r--r--core/SCsub2
-rw-r--r--core/bind/core_bind.cpp39
-rw-r--r--core/bind/core_bind.h3
-rw-r--r--core/globals.cpp6
-rw-r--r--core/image.cpp20
-rw-r--r--core/image.h9
-rw-r--r--core/io/config_file.cpp7
-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/object_saver_base.h76
-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/quick_hull.cpp3
-rw-r--r--core/object.cpp2
-rw-r--r--core/register_core_types.cpp35
-rw-r--r--core/ustring.cpp36
-rw-r--r--core/ustring.h1
-rw-r--r--core/variant_call.cpp25
-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/player.gd3
-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 -> 23916 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.gd5
-rw-r--r--drivers/SCsub2
-rw-r--r--drivers/gles1/rasterizer_gles1.cpp19
-rw-r--r--drivers/gles1/rasterizer_gles1.h11
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp620
-rw-r--r--drivers/gles2/rasterizer_gles2.h29
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp10
-rw-r--r--drivers/gles2/shader_compiler_gles2.h3
-rw-r--r--drivers/gles2/shaders/copy.glsl20
-rw-r--r--drivers/gles2/shaders/material.glsl68
-rw-r--r--drivers/ogg/SCsub3
-rw-r--r--drivers/squish/image_compress_squish.cpp17
-rw-r--r--drivers/theora/SCsub3
-rw-r--r--drivers/theoraplayer/SCsub14
-rw-r--r--drivers/theoraplayer/video_stream_theoraplayer.cpp15
-rw-r--r--drivers/vorbis/SCsub6
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--drivers/windows/dir_access_windows.cpp12
-rw-r--r--main/SCsub2
-rw-r--r--main/main.cpp14
-rwxr-xr-xmethods.py14
-rw-r--r--modules/SCsub2
-rw-r--r--modules/gdscript/gd_compiler.cpp10
-rw-r--r--modules/gdscript/gd_editor.cpp9
-rw-r--r--modules/gdscript/gd_parser.cpp155
-rw-r--r--modules/gdscript/gd_parser.h2
-rw-r--r--modules/gdscript/gd_script.cpp61
-rw-r--r--modules/gdscript/gd_script.h14
-rw-r--r--modules/gdscript/gd_tokenizer.cpp18
-rw-r--r--modules/gdscript/gd_tokenizer.h1
-rw-r--r--modules/gdscript/register_types.cpp4
-rw-r--r--modules/gridmap/grid_map.cpp2
-rw-r--r--platform/android/SCsub4
-rw-r--r--platform/android/detect.py29
-rw-r--r--platform/android/export/export.cpp44
-rw-r--r--platform/flash/SCsub1
-rw-r--r--platform/flash/detect.py1
-rw-r--r--platform/iphone/SCsub11
-rw-r--r--platform/iphone/app_delegate.mm6
-rw-r--r--platform/iphone/detect.py19
-rw-r--r--platform/isim/SCsub9
-rw-r--r--platform/isim/detect.py14
-rw-r--r--platform/javascript/SCsub4
-rw-r--r--platform/javascript/detect.py11
-rw-r--r--platform/osx/SCsub2
-rw-r--r--platform/osx/detect.py18
-rw-r--r--platform/osx/os_osx.mm15
-rw-r--r--platform/server/detect.py38
-rw-r--r--platform/windows/SCsub2
-rw-r--r--platform/windows/detect.py107
-rw-r--r--platform/windows/os_windows.cpp7
-rw-r--r--platform/winrt/SCsub5
-rw-r--r--platform/winrt/app.cpp162
-rw-r--r--platform/winrt/app.h51
-rw-r--r--platform/winrt/detect.py6
-rw-r--r--platform/winrt/gl_context_egl.cpp151
-rw-r--r--platform/winrt/gl_context_egl.h44
-rw-r--r--platform/winrt/os_winrt.cpp197
-rw-r--r--platform/winrt/os_winrt.h7
-rw-r--r--platform/x11/SCsub2
-rw-r--r--platform/x11/detect.py69
-rw-r--r--scene/2d/particles_2d.cpp8
-rw-r--r--scene/2d/physics_body_2d.cpp37
-rw-r--r--scene/2d/physics_body_2d.h7
-rw-r--r--scene/2d/sprite.cpp14
-rw-r--r--scene/2d/tile_map.cpp212
-rw-r--r--scene/2d/tile_map.h48
-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.cpp15
-rw-r--r--scene/3d/area.h5
-rw-r--r--scene/3d/baked_light_instance.cpp78
-rw-r--r--scene/3d/baked_light_instance.h42
-rw-r--r--scene/3d/camera.cpp54
-rw-r--r--scene/3d/camera.h3
-rw-r--r--scene/3d/car_body.cpp741
-rw-r--r--scene/3d/car_body.h170
-rw-r--r--scene/3d/collision_object.cpp56
-rw-r--r--scene/3d/collision_object.h9
-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.cpp50
-rw-r--r--scene/3d/immediate_geometry.h5
-rw-r--r--scene/3d/light.cpp51
-rw-r--r--scene/3d/light.h8
-rw-r--r--scene/3d/mesh_instance.cpp17
-rw-r--r--scene/3d/navigation.cpp14
-rw-r--r--scene/3d/navigation.h7
-rw-r--r--scene/3d/navigation_mesh.cpp6
-rw-r--r--scene/3d/physics_body.cpp22
-rw-r--r--scene/3d/physics_body.h5
-rw-r--r--scene/3d/physics_joint.cpp25
-rw-r--r--scene/3d/physics_joint.h5
-rw-r--r--scene/3d/skeleton.cpp16
-rw-r--r--scene/3d/skeleton.h2
-rw-r--r--scene/3d/vehicle_body.cpp13
-rw-r--r--scene/3d/visual_instance.cpp12
-rw-r--r--scene/3d/visual_instance.h1
-rw-r--r--scene/SCsub2
-rw-r--r--scene/animation/animation_player.cpp8
-rw-r--r--scene/animation/animation_player.h2
-rw-r--r--scene/audio/event_player.cpp4
-rw-r--r--scene/gui/base_button.cpp12
-rw-r--r--scene/gui/button_group.cpp3
-rw-r--r--scene/gui/dialogs.cpp2
-rw-r--r--scene/gui/label.cpp5
-rw-r--r--scene/gui/popup_menu.cpp2
-rw-r--r--scene/gui/tree.cpp3
-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/node.cpp1
-rw-r--r--scene/main/scene_main_loop.cpp20
-rw-r--r--scene/main/scene_main_loop.h10
-rw-r--r--scene/main/timer.cpp8
-rw-r--r--scene/main/viewport.cpp47
-rw-r--r--scene/main/viewport.h5
-rw-r--r--scene/register_scene_types.cpp61
-rw-r--r--scene/resources/SCsub1
-rw-r--r--scene/resources/animation.cpp10
-rw-r--r--scene/resources/animation.h4
-rw-r--r--scene/resources/baked_light.cpp94
-rw-r--r--scene/resources/baked_light.h25
-rw-r--r--scene/resources/image_path_finder.cpp427
-rw-r--r--scene/resources/image_path_finder.h84
-rw-r--r--scene/resources/material.cpp28
-rw-r--r--scene/resources/material.h7
-rw-r--r--scene/resources/mesh.cpp27
-rw-r--r--scene/resources/mesh.h1
-rw-r--r--scene/resources/mikktspace.c1890
-rw-r--r--scene/resources/mikktspace.h145
-rw-r--r--scene/resources/packed_scene.cpp46
-rw-r--r--scene/resources/scene_preloader.cpp853
-rw-r--r--scene/resources/shader_graph.cpp4
-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/scene_binds.cpp55
-rw-r--r--scene/scene_binds.h62
-rw-r--r--servers/SCsub2
-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.cpp10
-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/constraint_sw.h6
-rw-r--r--servers/physics/physics_server_sw.cpp38
-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.cpp1
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp2
-rw-r--r--servers/physics_2d/body_2d_sw.cpp30
-rw-r--r--servers/physics_2d/body_2d_sw.h6
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp7
-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/physics_2d_server_sw.cpp16
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h4
-rw-r--r--servers/physics_2d/space_2d_sw.cpp4
-rw-r--r--servers/physics_2d_server.cpp10
-rw-r--r--servers/physics_2d_server.h7
-rw-r--r--servers/physics_server.cpp16
-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.cpp18
-rw-r--r--servers/visual/rasterizer.h11
-rw-r--r--servers/visual/rasterizer_dummy.cpp20
-rw-r--r--servers/visual/rasterizer_dummy.h11
-rw-r--r--servers/visual/shader_language.cpp2
-rw-r--r--servers/visual/visual_server_raster.cpp705
-rw-r--r--servers/visual/visual_server_raster.h84
-rw-r--r--servers/visual/visual_server_wrap_mt.h21
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h42
-rw-r--r--tools/SCsub2
-rw-r--r--tools/collada/collada.cpp13
-rw-r--r--tools/collada/collada.h24
-rw-r--r--tools/doc/doc_data.cpp5
-rw-r--r--tools/docdump/makemd.py2
-rw-r--r--tools/editor/editor_file_system.cpp2
-rw-r--r--tools/editor/editor_help.cpp2
-rw-r--r--tools/editor/editor_node.cpp109
-rw-r--r--tools/editor/editor_settings.cpp4
-rw-r--r--tools/editor/editor_shape_gizmos.cpp468
-rw-r--r--tools/editor/editor_shape_gizmos.h60
-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_collision_polygon.pngbin0 -> 419 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_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/io_plugins/editor_font_import_plugin.cpp16
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp32
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.cpp96
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.h12
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp34
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.h4
-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.cpp84
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp18
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h5
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp227
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.h68
-rw-r--r--tools/editor/plugins/sample_player_editor_plugin.cpp5
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp4
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp348
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.h47
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.cpp144
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.cpp5
-rw-r--r--tools/editor/project_export.cpp8
-rw-r--r--tools/editor/project_manager.cpp6
-rw-r--r--tools/editor/scenes_dock.cpp7
-rw-r--r--tools/editor/spatial_editor_gizmos.cpp204
-rw-r--r--tools/editor/spatial_editor_gizmos.h15
-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.py602
337 files changed, 9438 insertions, 12715 deletions
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/SConstruct b/SConstruct
index de7256f6bc..fc9c7dca35 100644
--- a/SConstruct
+++ b/SConstruct
@@ -8,15 +8,6 @@ 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()
# scan possible build platforms
@@ -58,8 +49,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 +89,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 +111,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
@@ -152,7 +136,6 @@ Help(opts.GenerateHelpText(env_base)) # generate help
env_base.Append(CPPPATH=['#core','#core/math','#tools','#drivers','#'])
# configure ENV for platform
-env_base.detect_python=True
env_base.platform_exporters=platform_exporters
"""
@@ -170,17 +153,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 +189,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 +242,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 +256,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 +300,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 +312,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/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..c66416ea6d 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -856,6 +856,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 +906,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 +916,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);
}
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 0ef70e4b13..2d824955df 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -233,9 +233,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/globals.cpp b/core/globals.cpp
index 5be53fd853..94fa331bed 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;
diff --git a/core/image.cpp b/core/image.cpp
index d9ba6c1594..ae9fb0adc4 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -1998,6 +1998,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..0084a3616f 100644
--- a/core/image.h
+++ b/core/image.h
@@ -216,6 +216,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.
@@ -325,6 +333,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/io/config_file.cpp b/core/io/config_file.cpp
index 45e8cf69ab..b707fd9c13 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;
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/object_saver_base.h b/core/io/object_saver_base.h
deleted file mode 100644
index d9ec4a3aba..0000000000
--- a/core/io/object_saver_base.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*************************************************************************/
-/* object_saver_base.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_BASE_H
-#define OBJECT_SAVER_BASE_H
-
-
-#ifdef OLD_SCENE_FORMAT_ENABLED
-#include "object_saver.h"
-
-#include "map.h"
-#include "resource.h"
-
-class ObjectSaverBase : public ObjectFormatSaver {
-
-protected:
-
- 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 _find_resources(const Variant& p_variant);
-
- virtual Error write()=0;
-public:
-
- virtual Error save(const Object *p_object,const Variant &p_meta);
-
- ObjectSaverBase();
- ~ObjectSaverBase();
-};
-
-#endif
-#endif // OBJECT_SAVER_BASE_H
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/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/object.cpp b/core/object.cpp
index b011d1ad3d..42d570042f 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);
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 473cf8706f..492068f604 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -27,8 +27,6 @@
/* 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/config_file.h"
@@ -56,14 +54,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 +91,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 );
@@ -212,10 +185,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 +197,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/ustring.cpp b/core/ustring.cpp
index cd33c276a8..d75c21d16e 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;
diff --git a/core/ustring.h b/core/ustring.h
index 4831341866..8fe3a95463 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -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_call.cpp b/core/variant_call.cpp
index e0ae7e2114..bd731abeaf 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)\
@@ -551,6 +551,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 +606,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 );
@@ -1313,6 +1333,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 +1451,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());
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/player.gd b/demos/2d/kinematic_char/player.gd
index 5c56477758..9cff0269e8 100644
--- a/demos/2d/kinematic_char/player.gd
+++ b/demos/2d/kinematic_char/player.gd
@@ -74,6 +74,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/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..080bd8ea17
--- /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..d9fa308a2f 100644
--- a/demos/misc/autoload/global.gd
+++ b/demos/misc/autoload/global.gd
@@ -9,11 +9,6 @@ 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
diff --git a/drivers/SCsub b/drivers/SCsub
index b50c5afbf2..bfd35344ea 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -82,7 +82,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/gles1/rasterizer_gles1.cpp b/drivers/gles1/rasterizer_gles1.cpp
index 02de063bda..00fc85c41c 100644
--- a/drivers/gles1/rasterizer_gles1.cpp
+++ b/drivers/gles1/rasterizer_gles1.cpp
@@ -5365,6 +5365,18 @@ Variant RasterizerGLES1::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar
}
+/* SAMPLED LIGHT */
+
+RID RasterizerGLES1::sampled_light_dp_create(int p_width,int p_height) {
+
+ return sampled_light_owner.make_rid(memnew(SampledLight));
+}
+
+void RasterizerGLES1::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) {
+
+
+}
+
/*MISC*/
bool RasterizerGLES1::is_texture(const RID& p_rid) const {
@@ -5559,6 +5571,13 @@ void RasterizerGLES1::free(const RID& 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/drivers/gles1/rasterizer_gles1.h b/drivers/gles1/rasterizer_gles1.h
index cca953eed0..0995089dd7 100644
--- a/drivers/gles1/rasterizer_gles1.h
+++ b/drivers/gles1/rasterizer_gles1.h
@@ -488,6 +488,13 @@ class RasterizerGLES1 : public Rasterizer {
mutable RID_Owner<Environment> environment_owner;
+ struct SampledLight {
+
+ int w,h;
+ };
+
+ mutable RID_Owner<SampledLight> sampled_light_owner;
+
struct ShadowBuffer;
struct LightInstance {
@@ -1190,6 +1197,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/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index ecf80047bd..bb0fd2e593 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
@@ -303,9 +310,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 +337,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
@@ -333,7 +370,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_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_NV:GL_LUMINANCE;
} break;
case Image::FORMAT_INTENSITY: {
@@ -341,14 +378,14 @@ 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;
+ r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA;
r_has_alpha_cache=true;
} break;
case Image::FORMAT_GRAYSCALE_ALPHA: {
//image.convert(Image::FORMAT_RGBA);
r_gl_components=2;
- r_gl_format=GL_LUMINANCE_ALPHA;
+ r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_ALPHA_NV:GL_LUMINANCE_ALPHA;
r_has_alpha_cache=true;
} break;
@@ -357,7 +394,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
if (!image.empty())
image.convert(Image::FORMAT_RGB);
r_gl_components=3;
- r_gl_format=GL_RGB;
+ r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB;
} break;
@@ -366,54 +403,113 @@ 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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_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_format=_GL_SRGB_EXT;
+ } else {
+ r_gl_format=GL_RGB;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_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_format=_GL_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_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_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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_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_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 +517,29 @@ 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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_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_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 +547,29 @@ 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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_EXT_COMPRESSED_RED_RGTC1;
+ r_gl_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT;
r_gl_components=1; //doesn't matter much
r_compressed=true;
};
@@ -459,36 +577,58 @@ 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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_EXT_COMPRESSED_RG_RGTC2;
+ r_gl_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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
+ r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
r_gl_components=1; //doesn't matter much
r_compressed=true;
@@ -497,18 +637,30 @@ 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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
+ r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
r_gl_components=1; //doesn't matter much
r_compressed=true;
@@ -517,16 +669,27 @@ 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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
+ r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
r_gl_components=1; //doesn't matter much
r_compressed=true;
}
@@ -534,16 +697,27 @@ 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_SRGB_ALPHA_EXT;
+ } else {
+ r_gl_format=GL_RGBA;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_format=GL_RGBA;
+ }
r_has_alpha_cache=true;
} else {
- r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
+ r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
r_gl_components=1; //doesn't matter much
r_compressed=true;
}
@@ -551,12 +725,24 @@ 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;
+ if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
+
+ if (srgb_supported) {
+ r_gl_format=_GL_SRGB_EXT;
+ } else {
+ r_gl_format=GL_RGB;
+ if (!image.empty())
+ image.srgb_to_linear();
+ }
+ } else {
+ r_gl_format=GL_RGB;
+ }
r_gl_format=GL_RGB;
@@ -800,6 +986,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;
@@ -1047,6 +1243,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
@@ -1399,6 +1605,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;
}
@@ -4212,7 +4419,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 +4434,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");
}
@@ -4656,6 +4866,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) {
@@ -4897,7 +5108,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 +5119,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 +5163,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 +5173,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 +5183,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 +5240,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 +5336,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 +5347,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 +5369,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 +5396,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 +5429,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 +5445,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 +5472,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 +5602,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 +5739,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 +6043,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 +6092,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 +6111,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 +6233,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 +6259,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 +6291,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 +6367,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 +6384,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 +6402,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 +7136,7 @@ void RasterizerGLES2::end_scene() {
_debug_shadows();
}
// _debug_luminances();
+ _debug_samplers();
}
@@ -7193,6 +7537,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();
@@ -7810,6 +8186,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 +8477,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 +9072,15 @@ 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;
+
+ 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 +9100,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 +9164,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..91395054d9 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,6 +98,8 @@ 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;
@@ -601,7 +610,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 +706,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 +815,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 +1086,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();
+
/***********/
@@ -1524,6 +1548,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..50b63e1aa0 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -176,6 +176,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
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;
}
@@ -546,6 +549,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
uses_screen_uv=false;
uses_light=false;
uses_time=false;
+ uses_normalmap=false;
vertex_code_writes_vertex=false;
uniforms=r_uniforms;
flags=&r_flags;
@@ -555,6 +559,7 @@ 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;
String error;
int errline,errcol;
@@ -576,8 +581,10 @@ 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_code_line=code;
r_globals_line=global_code;
+
return OK;
}
@@ -670,6 +677,8 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
mode_replace_table[1]["NORMAL"]="normal";
mode_replace_table[1]["TANGENT"]="tangent";
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";
@@ -728,5 +737,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
vname_vertex="VERTEX";
vname_light="LIGHT";
vname_time="TIME";
+ vname_normalmap="NORMALMAP";
}
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 3dfdd81c0d..5012414c8b 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -50,6 +50,7 @@ private:
bool uses_discard;
bool uses_time;
bool uses_screen_uv;
+ bool uses_normalmap;
bool vertex_code_writes_vertex;
Flags *flags;
@@ -66,6 +67,7 @@ private:
StringName vname_vertex;
StringName vname_light;
StringName vname_time;
+ StringName vname_normalmap;
Map<StringName,ShaderLanguage::Uniform> *uniforms;
@@ -87,6 +89,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;
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..7d9aca4b4d 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
@@ -809,6 +827,12 @@ void main() {
vec4 color = color_interp;
#endif
+#if defined(ENABLE_NORMALMAP)
+
+ vec3 normalmap = vec3(0.0);
+#endif
+
+ float normaldepth=1.0;
@@ -823,6 +847,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 +926,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 +942,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
@@ -1202,7 +1252,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/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/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..979ff2ed1b 100644
--- a/drivers/theoraplayer/SCsub
+++ b/drivers/theoraplayer/SCsub
@@ -59,7 +59,6 @@ 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
""")
if env["platform"] == "iphone":
@@ -79,7 +78,18 @@ if env["platform"] == "android":
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/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp
index 12ef5de88f..b2ff8062cc 100644
--- a/drivers/theoraplayer/video_stream_theoraplayer.cpp
+++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp
@@ -86,12 +86,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)
@@ -366,6 +372,10 @@ void VideoStreamTheoraplayer::update(float p_time) {
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);
};
@@ -377,10 +387,11 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) {
std::string file = p_file.replace("res://", "").utf8().get_data();
clip = mgr->createVideoClip(file);
+ memdelete(f);
} else {
- TheoraDataSource* ds = memnew(TPDataFA(p_file));
+ TheoraDataSource* ds = memnew(TPDataFA(f, p_file));
try {
clip = mgr->createVideoClip(ds);
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/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index aefec59ce0..df6cc6c5e2 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -189,10 +189,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 +210,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,7 +352,7 @@ 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);
@@ -361,7 +361,7 @@ bool DirAccessWindows::dir_exists(String p_dir) {
DWORD fileAttr;
fileAttr = GetFileAttributesExA(p_dir.ascii().get_data(), GetFileExInfoStandard, &fileInfo);
- if (0xFFFFFFFF == fileAttr)
+ if (0 == fileAttr)
return false;
return (fileAttr&FILE_ATTRIBUTE_DIRECTORY);
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..fa7ce50c6d 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"
@@ -1131,10 +1131,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 +1210,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/methods.py b/methods.py
index 58cc41f70a..77da82fe24 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\","
@@ -1330,7 +1330,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..4c56468297 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gd_compiler.cpp
@@ -179,7 +179,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
//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)
}
}
@@ -1507,8 +1507,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);
}
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index a98b07ab92..d1f511b46e 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -114,6 +114,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 +123,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 +250,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));
}
}
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index 46eade0b7c..659e19a9d0 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -372,10 +372,26 @@ 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 idn( tokenizer->get_token_identifier() );
+
+ for( int i=0; i<cln->constant_expressions.size(); ++i ) {
+
+ if( cln->constant_expressions[i].identifier == idn ) {
+ tokenizer->advance();
+ expr = cln->constant_expressions[i].expression;
+ bfn = true;
+ break;
+ }
+ }
+
+ if( !bfn ) {
+ IdentifierNode *id = alloc_node<IdentifierNode>();
+ id->name = idn;
+ tokenizer->advance();
+ 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) {
@@ -1179,7 +1195,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;
}
@@ -2360,80 +2376,113 @@ void GDParser::_parse_class(ClassNode *p_class) {
member._export.name=member.identifier;
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;
+ if (autoexport) {
+ if (subexpr->type==Node::TYPE_ARRAY) {
- subexpr = _parse_and_reduce_expression(p_class,false);
- if (!subexpr)
- return;
+ member._export.type=Variant::ARRAY;
- if (autoexport) {
- if (subexpr->type==Node::TYPE_ARRAY) {
+ } else if (subexpr->type==Node::TYPE_DICTIONARY) {
- p_class->variables[p_class->variables.size()-1]._export.type=Variant::ARRAY;
+ member._export.type=Variant::DICTIONARY;
- } else if (subexpr->type==Node::TYPE_DICTIONARY) {
+ } else {
- p_class->variables[p_class->variables.size()-1]._export.type=Variant::DICTIONARY;
+ if (subexpr->type!=Node::TYPE_CONSTANT) {
- } else {
+ _set_error("Type-less export needs a constant expression assigned to infer type.");
+ return;
+ }
- if (subexpr->type!=Node::TYPE_CONSTANT) {
+ ConstantNode *cn = static_cast<ConstantNode*>(subexpr);
+ if (cn->value.get_type()==Variant::NIL) {
- _set_error("Type-less export needs a constant expression assigned to infer type.");
- return;
+ _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_ASSIGN;
+ op->arguments.push_back(id);
+ op->arguments.push_back(subexpr);
- 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;
+#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) {
+
+ _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();
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index 50b84d389a..16a9a85290 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -82,6 +82,8 @@ public:
Variant default_value;
#endif
StringName identifier;
+ StringName setter;
+ StringName getter;
};
struct Constant {
StringName identifier;
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 49d92e0746..b20fc51a03 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -1537,7 +1537,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);
@@ -1626,9 +1626,11 @@ void GDScript::set_source_code(const String& p_code) {
source=p_code;
}
-void GDScript::update_exports() {
+
+void GDScript::_update_exports(Set<PlaceHolderScriptInstance*> *p_instances) {
#ifdef TOOLS_ENABLED
+
String basedir=path;
if (basedir=="")
@@ -1645,8 +1647,20 @@ void GDScript::update_exports() {
const GDParser::Node* root = parser.get_parse_tree();
ERR_FAIL_COND(root->type!=GDParser::Node::TYPE_CLASS);
+
+
const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode*>(root);
+ if (c->extends_used && String(c->extends_file)!="") {
+
+ Ref<GDScript> bf = ResourceLoader::load(c->extends_file);
+ if (bf.is_valid()) {
+
+ bf->_update_exports(p_instances);
+
+ }
+ }
+
List<PropertyInfo> plist;
Map<StringName,Variant> default_values;
@@ -1660,10 +1674,19 @@ void GDScript::update_exports() {
}
- for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
+ for (Set<PlaceHolderScriptInstance*>::Element *E=p_instances->front();E;E=E->next()) {
E->get()->update(plist,default_values);
}
+#endif
+}
+
+void GDScript::update_exports() {
+
+#ifdef TOOLS_ENABLED
+
+ _update_exports(&placeholders);
+
#endif
}
@@ -1938,9 +1961,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();
}
@@ -1979,11 +2002,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 +2046,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 +2145,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,7 +2447,6 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"func" ,
"if" ,
"in" ,
- "varl",
"null" ,
"return" ,
"self" ,
@@ -2419,6 +2455,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"false" ,
"tool",
"var",
+ "setget",
"pass",
"and",
"or",
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 2088606271..3b183a41b6 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -220,11 +220,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,7 +241,7 @@ 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
@@ -263,6 +270,9 @@ friend class GDFunctions;
#endif
+
+ void _update_exports(Set<PlaceHolderScriptInstance *> *p_instances);
+
protected:
bool _get(const StringName& p_name,Variant &r_ret) const;
bool _set(const StringName& p_name, const Variant& p_value);
@@ -285,7 +295,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;
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index 7a1d6814ba..0fa83b9eb4 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",
@@ -237,7 +238,9 @@ void GDTokenizerText::_advance() {
while (true) {
- bool is_node_path=false;
+ bool is_node_path = false;
+ bool is_string = false;
+ bool is_string_alt = false;
switch(GETCHAR(0)) {
case 0:
@@ -527,13 +530,17 @@ 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 '\'':
+ is_string_alt = true;
case '"': {
+ is_string = is_string_alt ? false : true;
int i=1;
String str;
@@ -542,8 +549,10 @@ void GDTokenizerText::_advance() {
_make_error("Unterminated String");
return;
- } else if (CharType(GETCHAR(i)=='"')) {
+ } else if( CharType(GETCHAR(i)=='"') && is_string ) {
break;
+ } else if( CharType(GETCHAR(i)=='\'') && is_string_alt ) {
+ break;
} else if (CharType(GETCHAR(i)=='\\')) {
//escaped characters...
i++;
@@ -823,6 +832,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 +1017,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..4f9522fb56 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,
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index 8b46773502..543eecdf8b 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();
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..7c10c474c3 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -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/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..417f3e68ab 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,7 +122,7 @@ 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')
elif env["armv6"]!="no":
@@ -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..bcc818dac8 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 ) );
@@ -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=false;
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/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..9fc90bc84e 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -35,11 +35,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.mm b/platform/iphone/app_delegate.mm
index 9877e09ade..76c2d06080 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -257,7 +257,8 @@ 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];
}
@@ -282,7 +283,8 @@ 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
}
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 2065d459cd..c25742a854 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -34,9 +34,7 @@ def get_opts():
def get_flags():
return [
- ('lua', 'no'),
('tools', 'no'),
- ('nedmalloc', 'no'),
('webp', 'yes'),
('openssl','builtin'), #use builtin openssl
]
@@ -47,10 +45,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'
@@ -101,15 +95,11 @@ def configure(env):
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']
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"):
@@ -130,9 +120,10 @@ def configure(env):
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/isim/SCsub b/platform/isim/SCsub
index e7de935b2e..07761486a9 100644
--- a/platform/isim/SCsub
+++ b/platform/isim/SCsub
@@ -34,11 +34,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..f4a17838f9 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'
@@ -83,8 +77,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 +91,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/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/detect.py b/platform/osx/detect.py
index 5337416074..1b32838525 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'])
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index c09dadc066..643c287c95 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1070,7 +1070,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 {
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..08a775e689 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -10,4 +10,4 @@ common_win=[
"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..16f70b60d0 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'])
@@ -117,7 +115,8 @@ def configure(env):
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
env.Append(CCFLAGS=['/DGLES1_ENABLED'])
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
- env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', '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")):
@@ -139,47 +138,57 @@ def configure(env):
#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'])
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 81a96ccb13..7c2385e103 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -982,8 +982,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 +998,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;
diff --git a/platform/winrt/SCsub b/platform/winrt/SCsub
index c83f4fab32..07e2ba81a6 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_rt', files)
diff --git a/platform/winrt/app.cpp b/platform/winrt/app.cpp
new file mode 100644
index 0000000000..e3213d574a
--- /dev/null
+++ b/platform/winrt/app.cpp
@@ -0,0 +1,162 @@
+//
+// This file demonstrates how to initialize EGL in a Windows Store app, using ICoreWindow.
+//
+
+#include "app.h"
+
+#include "main/main.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^ 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
+
+ // 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));
+}
+
+// Initializes scene resources
+void App::Load(Platform::String^ entryPoint)
+{
+ char** args = {NULL};
+ Main::setup("winrt", 0, 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.
+#endif
+}
+
+void App::UpdateWindowSize(Size size)
+{
+ /*
+ DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
+ Size pixelSize(ConvertDipsToPixels(size.Width, currentDisplayInformation->LogicalDpi), ConvertDipsToPixels(size.Height, currentDisplayInformation->LogicalDpi));
+
+ mWindowWidth = static_cast<GLsizei>(pixelSize.Width);
+ mWindowHeight = static_cast<GLsizei>(pixelSize.Height);
+ */
+}
diff --git a/platform/winrt/app.h b/platform/winrt/app.h
new file mode 100644
index 0000000000..a67b936cdf
--- /dev/null
+++ b/platform/winrt/app.h
@@ -0,0 +1,51 @@
+#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 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;
+
+ OSWinrt* os;
+ };
+
+}
diff --git a/platform/winrt/detect.py b/platform/winrt/detect.py
index d09688b71c..00913b0ade 100644
--- a/platform/winrt/detect.py
+++ b/platform/winrt/detect.py
@@ -57,13 +57,13 @@ def configure(env):
env.Append(CCFLAGS=['-g','-pg'])
env.Append(LINKFLAGS=['-pg'])
- env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/ZW', '/EHsc'])
- env.Append(CXXFLAGS=['/TP'])
+ 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=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000'])
env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
#env.Append(CCFLAGS=['/DWIN32'])
env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
diff --git a/platform/winrt/gl_context_egl.cpp b/platform/winrt/gl_context_egl.cpp
new file mode 100644
index 0000000000..ca592c5d19
--- /dev/null
+++ b/platform/winrt/gl_context_egl.cpp
@@ -0,0 +1,151 @@
+#include "gl_context_egl.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::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 {
+
+ display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ 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..56bf654ee5
--- /dev/null
+++ b/platform/winrt/gl_context_egl.h
@@ -0,0 +1,44 @@
+#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 cleanup();
+
+ ContextEGL(CoreWindow^ p_window);
+ ~ContextEGL();
+
+};
+
+#endif
+
diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp
index 16a74c877c..99c4ad968e 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;
@@ -129,59 +137,18 @@ 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;
+void OSWinrt::set_gl_context(ContextEGL* p_context) {
- switch (uMsg) {
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN: {
-
- event.screen_touch.pressed = true;
- } break;
-
- 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) {
-
- 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);
-};
-
-
void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
-
-
main_loop=NULL;
outside=true;
-
+ gl_context->initialize();
+
visual_server = memnew( VisualServerRaster(rasterizer) );
if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) {
@@ -222,6 +189,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 +223,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,6 +265,8 @@ String OSWinrt::get_clipboard() const {
CloseClipboard();
return ret;
+ */
+ return "";
};
@@ -327,10 +299,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 +323,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 +362,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) {
@@ -445,71 +405,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]) {
-
- 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);
+ if (p_rationale && p_rationale[0]) {
- } 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);
+ 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);
- 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 +471,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 +512,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;
}
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 +527,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();
}
@@ -665,23 +554,22 @@ Error OSWinrt::shell_open(String p_uri) {
String OSWinrt::get_locale() const {
Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag;
- return language.Data();
+ return language->Data();
}
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 +587,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 +613,7 @@ String OSWinrt::get_data_dir() const {
}
-OSWinrt::OSWinrt(HINSTANCE _hInstance) {
+OSWinrt::OSWinrt() {
key_event_pos=0;
force_quit=false;
@@ -743,6 +632,8 @@ OSWinrt::OSWinrt(HINSTANCE _hInstance) {
stdo=fopen("stdout.txt","wb");
#endif
+ gl_context = NULL;
+
}
diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h
index bc7e188c20..c309239af1 100644
--- a/platform/winrt/os_winrt.h
+++ b/platform/winrt/os_winrt.h
@@ -41,11 +41,10 @@
#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
#include "servers/physics_2d/physics_2d_server_sw.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 +92,8 @@ class OSWinrt : public OS {
Physics2DServer *physics_2d_server;
int pressrc;
+ ContextEGL* gl_context;
+
struct Joystick {
int id;
@@ -224,6 +225,8 @@ public:
virtual void move_window_to_foreground();
virtual String get_data_dir() const;
+ void set_gl_context(ContextEGL* p_context);
+
virtual void release_rendering_thread();
virtual void make_rendering_thread();
virtual void swap_buffers();
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..03de91fa2f 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -47,22 +47,29 @@ 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')
]
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 +78,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 +112,20 @@ 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'])
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"]=="32"):
+ env.Append(CPPFLAGS=['-m64'])
+ env.Append(LINKFLAGS=['-m64','-L/usr/lib/i686-linux-gnu'])
if (env["CXX"]=="clang++"):
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index ded86702ef..819b06e095 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -507,7 +507,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)
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 78b5e23da0..308aa8402f 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -250,7 +250,7 @@ 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().rc=0;
E->get().in_scene=node && node->is_inside_scene();
if (node) {
node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid));
@@ -260,8 +260,9 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap
}
}
+ //E->get().rc++;
}
- E->get().rc++;
+
if (node)
E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape));
@@ -272,24 +273,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)
+ 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 +384,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 +392,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);
@@ -920,6 +925,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) {
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;
}
}
@@ -1008,6 +1015,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 +1092,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 +1130,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..e429ca1432 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -156,7 +156,7 @@ private:
};
struct BodyState {
- int rc;
+ //int rc;
bool in_scene;
VSet<ShapePair> shapes;
};
@@ -254,7 +254,8 @@ class KinematicBody2D : public PhysicsBody2D {
Vector2 normal;
Vector2 collider_vel;
ObjectID collider;
-
+ int collider_shape;
+ Variant collider_metadata;
Variant _get_collider() const;
@@ -273,6 +274,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/sprite.cpp b/scene/2d/sprite.cpp
index 7d033ed87f..8c3bbfdfc9 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -64,20 +64,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 +85,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;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 6403454588..eb04ca924f 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -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;
}
@@ -171,6 +171,7 @@ void TileMap::_update_dirty_quadrants() {
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 );
@@ -341,7 +352,6 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const
}
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;
@@ -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/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..7370c36eb7 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -255,16 +255,6 @@ bool Area::is_monitoring_enabled() const {
}
-void Area::set_ray_pickable(bool p_ray_pickable) {
-
- ray_pickable=p_ray_pickable;
- PhysicsServer::get_singleton()->area_set_ray_pickable(get_rid(),p_ray_pickable);
-}
-
-bool Area::is_ray_pickable() const {
-
- return ray_pickable;
-}
void Area::_bind_methods() {
@@ -289,8 +279,6 @@ 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);
@@ -310,7 +298,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"));
}
@@ -323,7 +310,7 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru
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..5558e2c719 100644
--- a/scene/3d/area.h
+++ b/scene/3d/area.h
@@ -52,7 +52,7 @@ private:
real_t density;
int priority;
bool monitoring;
- bool ray_pickable;
+
void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape);
@@ -109,9 +109,6 @@ 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;
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/camera.cpp b/scene/3d/camera.cpp
index 4245bfa2c9..ab28c0c8d4 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -219,11 +219,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 +244,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 +267,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) {
@@ -314,6 +319,20 @@ 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_scene())
+ return;
+ if (get_viewport()->get_camera()!=NULL)
+ return;
+
+ make_current();
+}
+
+
void Camera::clear_current() {
current=false;
@@ -321,8 +340,12 @@ void Camera::clear_current() {
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_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this);
+
+ }
}
}
@@ -444,7 +467,15 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const {
ERR_FAIL_COND_V(!is_inside_scene(),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,10 +487,9 @@ 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;
};
@@ -471,8 +501,14 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const {
ERR_FAIL_COND_V(!is_inside_scene(),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 +518,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();
@@ -636,6 +672,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 +732,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 +741,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);
}
@@ -732,7 +769,8 @@ Camera::Camera() {
mode=PROJECTION_PERSPECTIVE;
set_perspective(60.0,0.1,100.0);
keep_aspect=KEEP_HEIGHT;
- layers=0xFFFFFFFF;
+ layers=0xfffff;
+ 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..bac8173bb7 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -66,6 +66,8 @@ private:
RID camera;
RID scenario_id;
+ String camera_group;
+
uint32_t layers;
Viewport *viewport_ptr;
@@ -74,6 +76,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);
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..e9d3e73906 100644
--- a/scene/3d/collision_object.cpp
+++ b/scene/3d/collision_object.cpp
@@ -53,8 +53,9 @@ void CollisionObject::_notification(int p_what) {
} else
PhysicsServer::get_singleton()->body_set_space(rid,space);
+ _update_pickable();
//get space
- }
+ };
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -64,6 +65,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 +97,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);
+ }
}
}
@@ -160,18 +166,18 @@ void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const {
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::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
}
}
-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 +198,28 @@ void CollisionObject::_mouse_exit() {
}
+void CollisionObject::_update_pickable() {
+ if (!is_inside_scene())
+ return;
+ bool pickable = ray_pickable && is_inside_scene() && 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 +234,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 +327,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 +354,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/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..a4206894ff 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);
@@ -81,11 +128,14 @@ void ImmediateGeometry::_bind_methods() {
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_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/light.cpp b/scene/3d/light.cpp
index 1efc74e672..e51a9764f6 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -429,10 +429,42 @@ void Light::approximate_opengl_attenuation(float p_constant, float p_linear, flo
}
+
+void Light::_update_visibility() {
+
+ if (!is_inside_scene())
+ return;
+
+
+bool editor_ok=true;
+
+#ifdef TOOLS_ENABLED
+ if (editor_only) {
+ if (!get_scene()->is_editor_hint()) {
+ editor_ok=false;
+ } else {
+ editor_ok = (get_scene()->get_edited_scene_root() && (this==get_scene()->get_edited_scene_root() || get_owner()==get_scene()->get_edited_scene_root()));
+ }
+ }
+#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_SCENE || 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..72d63fa006 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) {
@@ -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,6 +215,12 @@ 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() );
+
}
@@ -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..d22198d47e 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);
@@ -453,6 +455,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 +474,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 +497,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 +505,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 +587,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..9b6cf5fbc4 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;
@@ -124,7 +129,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..db416f24dd 100644
--- a/scene/3d/navigation_mesh.cpp
+++ b/scene/3d/navigation_mesh.cpp
@@ -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);
}
}
@@ -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;
}
@@ -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/physics_body.cpp b/scene/3d/physics_body.cpp
index a99964cc54..15ec60514a 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -245,7 +245,7 @@ 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().rc=0;
E->get().in_scene=node && node->is_inside_scene();
if (node) {
node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid));
@@ -256,7 +256,7 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,
}
}
- E->get().rc++;
+ //E->get().rc++;
if (node)
E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape));
@@ -267,24 +267,26 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_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_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)
+ 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);
}
@@ -965,6 +967,7 @@ Vector3 KinematicBody::move(const Vector3& p_motion) {
normal=rest.normal;
collider=rest.collider_id;
collider_vel=rest.linear_velocity;
+ collider_shape=rest.shape;
}
}
@@ -1053,7 +1056,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 +1125,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 +1162,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..a19ad48c87 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -162,7 +162,7 @@ private:
};
struct BodyState {
- int rc;
+ //int rc;
bool in_scene;
VSet<ShapePair> shapes;
};
@@ -266,6 +266,8 @@ class KinematicBody : public PhysicsBody {
Vector3 normal;
Vector3 collider_vel;
ObjectID collider;
+ int collider_shape;
+
Variant _get_collider() const;
@@ -291,6 +293,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..8a79e17d87 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -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) {
@@ -117,8 +134,6 @@ void Joint::_notification(int p_what) {
case NOTIFICATION_EXIT_SCENE: {
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/skeleton.cpp b/scene/3d/skeleton.cpp
index 858ee4e4ad..737f7d2dce 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.inverse() * p_pose);
+ } else {
+
+ set_bone_pose(p_bone, bones[p_bone].rest.inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose));
+
+ }
+
+}
+
Transform Skeleton::get_bone_global_pose(int p_bone) const {
ERR_FAIL_INDEX_V(p_bone,bones.size(),Transform());
@@ -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/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index 07abd1dcd2..4cf905e4ee 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -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/visual_instance.cpp b/scene/3d/visual_instance.cpp
index af535e139f..398fbdea82 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;
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_player.cpp b/scene/animation/animation_player.cpp
index 030f3f27e0..9a3c7e71ec 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -180,6 +180,10 @@ 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) {
@@ -923,7 +927,7 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float
StringName next=animation_get_next(p_name);
- if (next!=StringName()) {
+ if (next!=StringName() && animation_set.has(next)) {
queue(next);
}
}
@@ -1227,6 +1231,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..038c43d569 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -283,6 +283,8 @@ 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;
diff --git a/scene/audio/event_player.cpp b/scene/audio/event_player.cpp
index 6bad94bf0e..e5b2be53ca 100644
--- a/scene/audio/event_player.cpp
+++ b/scene/audio/event_player.cpp
@@ -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/gui/base_button.cpp b/scene/gui/base_button.cpp
index ac2417d539..7745ce11fc 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -55,6 +55,9 @@ void BaseButton::_input_event(InputEvent p_event) {
if (b.pressed) {
if (!toggle_mode) { //mouse press attempt
+
+ status.press_attempt=true;
+ status.pressing_inside=true;
pressed();
emit_signal("pressed");
@@ -71,8 +74,15 @@ void BaseButton::_input_event(InputEvent p_event) {
}
+ } else {
+
+ if (status.press_attempt &&status.pressing_inside) {
+ pressed();
+ emit_signal("pressed");
+ }
+ status.press_attempt=false;
}
-
+ update();
break;
}
diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp
index 65cfd03505..58b323c24d 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());
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index ac0ded03ab..90393a1296 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -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/label.cpp b/scene/gui/label.cpp
index b7918994d8..36940655d4 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -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/popup_menu.cpp b/scene/gui/popup_menu.cpp
index c2dc1318c9..0ba3bdb7c6 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -855,7 +855,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);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 9084983a4c..a39c61ecac 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;
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/node.cpp b/scene/main/node.cpp
index 5d89ee80f1..e511a057c5 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"
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index bcdc50c880..c51974167d 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -968,6 +968,18 @@ void SceneMainLoop::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect
}
+#ifdef TOOLS_ENABLED
+void SceneMainLoop::set_edited_scene_root(Node *p_node) {
+ edited_scene_root=p_node;
+}
+
+Node *SceneMainLoop::get_edited_scene_root() const {
+
+ return edited_scene_root;
+}
+#endif
+
+
void SceneMainLoop::_bind_methods() {
@@ -983,6 +995,10 @@ void SceneMainLoop::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_editor_hint","enable"),&SceneMainLoop::set_editor_hint);
ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneMainLoop::is_editor_hint);
+#ifdef TOOLS_ENABLED
+ ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneMainLoop::set_edited_scene_root);
+ ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneMainLoop::get_edited_scene_root);
+#endif
ObjectTypeDB::bind_method(_MD("set_pause","enable"),&SceneMainLoop::set_pause);
ObjectTypeDB::bind_method(_MD("is_paused"),&SceneMainLoop::is_paused);
@@ -1069,6 +1085,10 @@ 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"));
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index 493644d2bc..bfa755ff7c 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -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,6 +226,13 @@ 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();
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index 25d1c8530e..8e80f868c6 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -36,8 +36,12 @@ void Timer::_notification(int p_what) {
case NOTIFICATION_READY: {
- if (autostart)
- start();
+ if (autostart) {
+#ifdef TOOLS_ENABLED
+ if (get_scene()->is_editor_hint() && get_scene()->get_edited_scene_root() && (get_scene()->get_edited_scene_root()==this || get_scene()->get_edited_scene_root()->is_a_parent_of(this)))
+ break;
+#endif start();
+ }
} break;
case NOTIFICATION_PROCESS: {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 92dcef803c..6b7ed66463 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);
@@ -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,6 +166,9 @@ 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();
}
@@ -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;
@@ -507,6 +515,7 @@ void Viewport::set_rect(const Rect2& p_rect) {
if (rect==p_rect)
return;
rect=p_rect;
+
_update_rect();
_update_stretch_transform();
@@ -541,7 +550,7 @@ Rect2 Viewport::get_rect() const {
void Viewport::_update_listener() {
- if (is_inside_scene() && audio_listener && camera) {
+ if (is_inside_scene() && 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 +561,7 @@ void Viewport::_update_listener() {
void Viewport::_update_listener_2d() {
- if (is_inside_scene() && audio_listener_2d)
+ if (is_inside_scene() && 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());
@@ -1023,13 +1032,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 +1056,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;
@@ -1179,6 +1191,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..37f1b357c6 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;
@@ -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..f3b13f30bf 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -32,7 +32,7 @@
#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"
@@ -100,6 +100,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 +120,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 +142,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"
@@ -173,9 +174,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 +185,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 +203,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 +215,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 +226,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 +246,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();
@@ -378,7 +352,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 +377,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 +386,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,6 +394,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<VisibilityNotifier>();
ObjectTypeDB::register_type<VisibilityEnabler>();
ObjectTypeDB::register_type<BakedLightInstance>();
+ ObjectTypeDB::register_type<BakedLightSampler>();
ObjectTypeDB::register_type<WorldEnvironment>();
//scenariofx
@@ -491,6 +463,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);
@@ -559,7 +532,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,10 +563,6 @@ 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>();
@@ -617,11 +586,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..e6359f920b 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1716,7 +1716,7 @@ void Animation::clear() {
}
-void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err) {
+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);
@@ -1779,6 +1779,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
} else {
+
Quat r02 = (q0.inverse() * q2).normalized();
Quat r01 = (q0.inverse() * q1).normalized();
@@ -1788,6 +1789,9 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
r02.get_axis_and_angle(v02,a02);
r01.get_axis_and_angle(v01,a01);
+ if (Math::abs(a02)>p_max_optimizable_angle)
+ continue;
+
if (v01.dot(v02)<0) {
//make sure both rotations go the same way to compare
v02=-v02;
@@ -1905,7 +1909,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 +1917,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..0c0290295a 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -204,7 +204,7 @@ private:
return idxr;
}
- void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01);
+ 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 +271,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/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/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..2c278f4fed 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++) {
@@ -540,6 +550,10 @@ 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("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 );
}
@@ -585,6 +599,8 @@ ParticleSystemMaterial::ParticleSystemMaterial() :Material(VisualServer::get_sin
set_depth_draw_mode(DEPTH_DRAW_NEVER);
VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_ALPHA,true);
VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);
+ set_flag(FLAG_COLOR_ARRAY_SRGB,true);
+
}
ParticleSystemMaterial::~ParticleSystemMaterial() {
@@ -655,6 +671,8 @@ UnshadedMaterial::UnshadedMaterial() :Material(VisualServer::get_singleton()->fi
set_flag(FLAG_UNSHADED,true);
set_use_alpha(true);
+ set_flag(FLAG_COLOR_ARRAY_SRGB,true);
+
}
UnshadedMaterial::~UnshadedMaterial() {
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 23ecb18fac..9c3feede08 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;
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index c6e492fcb3..3aeccdc551 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())
@@ -740,6 +765,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..d6ab6a1198 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -167,6 +167,7 @@ public:
Ref<Shape> create_convex_shape() 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..75a1b765ee 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,34 @@ 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 (instance_state[name]==value)
+ }*/
+
+ if (instance_state[name]==value) {
continue;
+ }
}
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_graph.cpp b/scene/resources/shader_graph.cpp
index df5fee81a8..3ed6cebf07 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -148,8 +148,8 @@ void ShaderGraph::_bind_methods() {
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 );
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..dd39205932 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/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/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/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..bca6a9fa72 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -175,7 +175,7 @@ void BodyPairSW::validate_contacts() {
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->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;
}
@@ -267,6 +267,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_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/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..510a6ea93f 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);
}
@@ -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..8be583c235 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -180,6 +180,7 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this),
gravity_vector=Vector2(0,-1);
gravity_is_point=false;
point_attenuation=1;
+
density=0.1;
priority=0;
monitor_callback_id=0;
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..fbad19f6be 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -176,6 +176,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 +187,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 +230,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());
@@ -385,10 +395,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) {
@@ -434,7 +444,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 +459,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 +517,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,6 +601,7 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti
island_next=NULL;
island_list_next=NULL;
_set_static(false);
+ first_time_kinematic=false;
density=0;
contact_count=0;
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index ffe47e0267..789fb1cfee 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -72,6 +72,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 +135,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(); }
@@ -334,6 +336,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..9abdd01791 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -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/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 09fa3f9b6a..ab85f5e1d6 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -548,6 +548,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);
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 7ffffe669f..9edd4eee11 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -149,10 +149,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);
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 21a99cd4b2..8b72436936 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -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++;
@@ -350,6 +352,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v
rd->best_object=rd->object;
rd->best_shape=rd->shape;
+
}
@@ -399,6 +402,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);
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index da8ac5f9c8..2760f9bea6 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -97,6 +97,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 +245,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 +264,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 +314,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 +416,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 +450,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);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 17a21e46a3..20d7c3ad28 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -71,6 +71,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 +164,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 +175,8 @@ public:
ObjectID collider_id;
Object *collider;
int shape;
+ Variant metadata;
+
};
@@ -190,6 +194,7 @@ public:
ObjectID collider_id;
int shape;
Vector2 linear_velocity; //velocity at contact point
+ Variant metadata;
};
@@ -360,10 +365,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;
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index dc8e4cc298..e6b2927fb4 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);
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..5e81bc960a 100644
--- a/servers/visual/rasterizer.cpp
+++ b/servers/visual/rasterizer.cpp
@@ -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;
}
@@ -610,6 +620,8 @@ Rasterizer::Rasterizer() {
_fixed_material_uv_xform_name="fmp_uv_xform";
_fixed_material_point_size_name="fmp_point_size";
+ 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..55625a2218 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -56,6 +56,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 +84,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 +104,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 +126,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++) {
@@ -499,6 +503,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 +515,7 @@ public:
float lightmap_multiplier;
int octree_steps;
Vector2 octree_tex_pixel_size;
+ Vector2 light_tex_pixel_size;
};
struct InstanceData {
@@ -517,6 +523,7 @@ public:
Transform transform;
RID skeleton;
RID material_override;
+ RID sampled_light;
Vector<RID> light_instances;
Vector<float> morph_values;
BakedLightData *baked_light;
@@ -582,6 +589,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..a671821e25 100644
--- a/servers/visual/rasterizer_dummy.cpp
+++ b/servers/visual/rasterizer_dummy.cpp
@@ -1679,6 +1679,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 +1828,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..44bca423a4 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 {
@@ -713,6 +720,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_language.cpp b/servers/visual/shader_language.cpp
index 14d35e89b1..ca219b13a4 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1042,6 +1042,8 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={
{ "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},
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 21ecd4030d..13ecd49b68 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -1109,8 +1109,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 +1127,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 +1160,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 +1199,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 +1215,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 +1294,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 +1382,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 +1406,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 +1966,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 +2123,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 +2186,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 +2811,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 +2990,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 +3109,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: {}
}
@@ -3531,6 +3802,15 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen
canvas_item->commands.push_back(bm);
};
+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 +4022,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 +4084,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 +5230,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 +5288,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 +5488,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 = powf(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 +5841,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 +6002,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
keep=true;
}
+
+
}
@@ -5400,6 +6016,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 +6102,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 +6123,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);
@@ -5591,26 +6230,30 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
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;
}
+ if (ci->sort_y) {
+
+ SortArray<CanvasItem*,CanvasItemPtrSort> sorter;
+ sorter.sort(child_items,child_item_count);
+ }
+
+
for(int i=0;i<child_item_count;i++) {
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);
- }
+ continue;
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
}
-#endif
+
if (s!=0) {
@@ -5746,19 +6389,12 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
rasterizer->canvas_set_clip(true,canvas_clip);
}
-#ifndef ONTOP_DISABLED
-
- for(int i=0;i<top_item_count;i++) {
-
- _render_canvas_item(top_items[i],xform,p_clip_rect,opacity);
- }
-
-#else
- for(int i=0;i<p_canvas_item->child_items.size();i++) {
+ for(int i=0;i<child_item_count;i++) {
- _render_canvas_item(p_canvas_item->child_items[i],xform,p_clip_rect,opacity);
+ if (!child_items[i]->ontop)
+ continue;
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
}
-#endif
if (ci->clip) {
@@ -5819,6 +6455,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 +6465,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 +6513,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
@@ -5975,7 +6613,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);
}
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 49e7996c59..3064f9ceb0 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)
@@ -90,12 +91,29 @@ class VisualServerRaster : public VisualServer {
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 +187,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 +198,8 @@ class VisualServerRaster : public VisualServer {
InstanceSet lights;
bool light_cache_dirty;
+
+
struct RoomInfo {
Transform affine_inverse;
@@ -235,6 +256,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 +285,7 @@ class VisualServerRaster : public VisualServer {
ParticlesInfo *particles_info;
PortalInfo * portal_info;
BakedLightInfo * baked_light_info;
+ BakedLightSamplerInfo * baked_light_sampler_info;
Instance() {
@@ -282,6 +321,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 +361,7 @@ class VisualServerRaster : public VisualServer {
List<RID> directional_lights;
RID environment;
+ RID fallback_environment;
Instance *dirty_instances;
@@ -328,7 +370,7 @@ class VisualServerRaster : public VisualServer {
-
+
struct CanvasItem {
@@ -446,13 +488,14 @@ class VisualServerRaster : public VisualServer {
bool clip;
bool visible;
bool ontop;
+ bool sort_y;
float opacity;
float self_opacity;
MaterialBlendMode blend_mode;
RID viewport;
mutable bool custom_rect;
- mutable bool rect_dirty;
+ mutable bool rect_dirty;
mutable Rect2 rect;
Vector<Command*> commands;
@@ -460,11 +503,18 @@ class VisualServerRaster : public VisualServer {
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() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; sort_y=false;}
~CanvasItem() { clear(); }
};
+ 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 +644,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 +682,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,6 +703,8 @@ 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);
void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform);
@@ -944,12 +1000,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 +1102,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 +1159,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 +1212,7 @@ 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_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..a4653b1013 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -909,6 +909,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 +922,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 +943,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 +1013,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 +1069,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 +1126,8 @@ 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);
+
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..ed04b0d09c 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -87,6 +87,7 @@ public:
MAX_PARTICLE_COLOR_PHASES=4,
MAX_PARTICLE_ATTRACTORS=4,
+
MAX_CURSORS = 8,
};
@@ -96,8 +97,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
};
@@ -166,6 +169,7 @@ public:
MATERIAL_FLAG_UNSHADED,
MATERIAL_FLAG_ONTOP,
MATERIAL_FLAG_LIGHTMAP_ON_UV2,
+ MATERIAL_FLAG_COLOR_ARRAY_SRGB,
MATERIAL_FLAG_MAX,
};
@@ -229,6 +233,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 +590,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 +831,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 +847,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 +922,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,6 +977,7 @@ 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_clear(RID p_item)=0;
virtual void canvas_item_raise(RID p_item)=0;
diff --git a/tools/SCsub b/tools/SCsub
index 528ffbf3c3..875663b849 100644
--- a/tools/SCsub
+++ b/tools/SCsub
@@ -13,7 +13,7 @@ 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])
diff --git a/tools/collada/collada.cpp b/tools/collada/collada.cpp
index e29888b433..7a842391a4 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"));
@@ -2513,6 +2521,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;
diff --git a/tools/collada/collada.h b/tools/collada/collada.h
index 360f54ec05..c5e5705105 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 {
diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp
index 319c1ad8b7..0bd21219bf 100644
--- a/tools/doc/doc_data.cpp
+++ b/tools/doc/doc_data.cpp
@@ -997,8 +997,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 +1007,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/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/editor_file_system.cpp b/tools/editor/editor_file_system.cpp
index daba52be03..76755666eb 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);
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index 819da4bb45..42260e70ba 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -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"));
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index a137b6cd34..701704fbfa 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,6 +69,7 @@
#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"
@@ -233,25 +232,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="";
}
@@ -886,65 +866,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: {
@@ -1679,28 +1600,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: {
@@ -2438,6 +2337,8 @@ void EditorNode::set_edited_scene(Node *p_scene) {
if (edited_scene && edited_scene->cast_to<Popup>())
edited_scene->cast_to<Popup>()->show(); //show popups
scene_tree_dock->set_edited_scene(edited_scene);
+ if (get_scene())
+ get_scene()->set_edited_scene_root(edited_scene);
if (edited_scene) {
if (p_scene->get_parent()!=scene_root)
@@ -3549,9 +3450,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");
@@ -4079,6 +3977,7 @@ EditorNode::EditorNode() {
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_settings.cpp b/tools/editor/editor_settings.cpp
index 6f1a24d7e8..bc88896ebb 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","");
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/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_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_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_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/io_plugins/editor_font_import_plugin.cpp b/tools/editor/io_plugins/editor_font_import_plugin.cpp
index 4b3e052907..6a6ee8c614 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;
}
@@ -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..e86356ebe9 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -694,6 +694,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 +719,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 +749,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 +784,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;
}
@@ -1670,16 +1675,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 +1698,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 +1729,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 +1742,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 +1761,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 +1773,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);
}
@@ -1829,14 +1841,14 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
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) {
+ if (f>=anim_length)
+ f=anim_length;
base_snapshots.push_back(f);
f+=snapshot_interval;
}
- 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 +1873,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;
}
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
index 2482728c87..27400344d3 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"
@@ -641,6 +642,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 +651,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}
};
@@ -896,7 +899,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 +911,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 +927,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 +961,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 +973,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 +983,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 +1014,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 +1213,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 +1287,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>()) {
@@ -1872,7 +1937,7 @@ 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);
@@ -1918,7 +1983,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 +2019,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);
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.h b/tools/editor/io_plugins/editor_scene_import_plugin.h
index 3b39f0c962..72b4089d89 100644
--- a/tools/editor/io_plugins/editor_scene_import_plugin.h
+++ b/tools/editor/io_plugins/editor_scene_import_plugin.h
@@ -100,8 +100,14 @@ 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 _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);
@@ -125,6 +131,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 +139,7 @@ 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,
};
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
index 760651bbfd..86f7787a9c 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
};
@@ -725,7 +729,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 +738,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 +938,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 +1004,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 +1037,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..d17b3c05c2 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.h
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.h
@@ -93,7 +93,9 @@ 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
};
virtual String get_name() const;
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..d08c9f6484
--- /dev/null
+++ b/tools/editor/plugins/baked_light_baker_cmpxchg.cpp
@@ -0,0 +1,84 @@
+
+#include "typedefs.h"
+
+
+#ifdef 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;
+ }
+}
+
+#elif (__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)) {}
+
+}
+
+#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..2f8393f102 100644
--- a/tools/editor/plugins/baked_light_editor_plugin.cpp
+++ b/tools/editor/plugins/baked_light_editor_plugin.cpp
@@ -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/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp
new file mode 100644
index 0000000000..b8a5bd3bbe
--- /dev/null
+++ b/tools/editor/plugins/mesh_editor_plugin.cpp
@@ -0,0 +1,227 @@
+#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_scene()->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_scene()->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_scene()->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_scene()->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_scene()->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;
+ }
+
+}
+
+void MeshInstanceEditor::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_menu_option",&MeshInstanceEditor::_menu_option);
+}
+
+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()->connect("item_pressed", this,"_menu_option");
+
+}
+
+
+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..557eb90148
--- /dev/null
+++ b/tools/editor/plugins/mesh_editor_plugin.h
@@ -0,0 +1,68 @@
+#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,
+ };
+
+ AcceptDialog *err_dialog;
+
+
+ Panel *panel;
+ MeshInstance *node;
+
+ LineEdit *surface_source;
+ LineEdit *mesh_source;
+
+
+ void _menu_option(int p_option);
+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/sample_player_editor_plugin.cpp b/tools/editor/plugins/sample_player_editor_plugin.cpp
index fa8a285e4e..f3d6fe65da 100644
--- a/tools/editor/plugins/sample_player_editor_plugin.cpp
+++ b/tools/editor/plugins/sample_player_editor_plugin.cpp
@@ -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..24e09111e2 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -1105,6 +1105,8 @@ void ScriptEditor::ensure_select_current() {
if (!ste)
return;
Ref<Script> script = ste->get_edited_script();
+
+ ste->get_text_edit()->grab_focus();
}
}
@@ -1284,7 +1286,7 @@ 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
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
index a5cddc20e6..e91e7a94fe 100644
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ b/tools/editor/plugins/spatial_editor_plugin.cpp
@@ -860,10 +860,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()) {
@@ -1925,6 +1934,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,7 +1971,7 @@ 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();
@@ -2055,6 +2085,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 +2105,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 +2136,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 +2163,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 +2189,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 +2210,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");
}
@@ -2322,6 +2375,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 +2389,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 +2425,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 +2439,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"];
@@ -2395,7 +2462,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 +2490,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();
}
@@ -2575,11 +2658,29 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
} else {
light_instance=VisualServer::get_singleton()->instance_create2(light,get_scene()->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 +2694,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 +2718,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 +2768,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,6 +2821,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), 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: {
@@ -2732,7 +2891,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;
}
@@ -2747,6 +2906,7 @@ void SpatialEditor::_init_indicators() {
light_instance=VisualServer::get_singleton()->instance_create2(light,get_scene()->get_root()->get_world()->get_scenario());
+
light_transform.rotate(Vector3(1,0,0),Math_PI/5.0);
VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform);
@@ -2805,10 +2965,12 @@ void SpatialEditor::_init_indicators() {
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_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);
}
@@ -2827,6 +2989,8 @@ void SpatialEditor::_init_indicators() {
// 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());
+ 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);
@@ -2862,6 +3026,8 @@ void SpatialEditor::_init_indicators() {
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());
+ 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,19 +3299,23 @@ 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");
+ VS::get_singleton()->scenario_set_fallback_environment(get_viewport()->find_world()->get_scenario(),viewport_environment->get_rid());
+
}
if (p_what==NOTIFICATION_ENTER_SCENE) {
gizmos = memnew( SpatialEditorGizmos );
_init_indicators();
-
+ _update_default_light_angle();
}
if (p_what==NOTIFICATION_EXIT_SCENE) {
@@ -3250,8 +3420,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 +3450,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 +3461,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 +3482,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,11 +3630,14 @@ 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("2 Viewports (Alt)",MENU_VIEW_USE_2_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_2);
p->add_check_item("3 Viewports",MENU_VIEW_USE_3_VIEWPORTS,KEY_MASK_ALT+KEY_3);
+ p->add_check_item("3 Viewports (Alt)",MENU_VIEW_USE_3_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_3);
p->add_check_item("4 Viewports",MENU_VIEW_USE_4_VIEWPORTS,KEY_MASK_ALT+KEY_4);
p->add_separator();
@@ -3507,42 +3733,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..1fdc97c49d 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;
@@ -343,9 +350,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 +389,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 +440,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 +460,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/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp
index 09f26c8ca0..a25997108b 100644
--- a/tools/editor/plugins/tile_map_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_map_editor_plugin.cpp
@@ -166,7 +166,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 +218,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 +229,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 +278,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 +322,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 +469,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.y/cell_size)-1;i<=(si.pos.y+si.size.y)/cell_size;i++) {
- int ofs = i*cell_size;
+ 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)-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 +575,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 +609,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 +629,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));
}
}
}
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/project_export.cpp b/tools/editor/project_export.cpp
index 22331c86bf..a0031ff456 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"
@@ -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() {
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index 5764f9f2d9..0c32a4ba75 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -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");
@@ -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");
diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp
index a23c9cead7..3f7c82d988 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"
@@ -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);
diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp
index 082878655c..04d5888861 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;
-}
-
/////
@@ -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/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..a92b97b8a9 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=[]
@@ -281,9 +297,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 +331,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):
+
+ mesh = node.data
+
- if (node.data in self.mesh_cache) and shapename==None:
+ 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)
+ else:
+ md=self.export_mesh(node,None,k)
+
+ 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 +479,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 +519,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 +568,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,21 +577,22 @@ 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 shapename != None:
- meshid = self.new_id("mesh_"+shapename)
- self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'_'+shapename+'">')
- else:
- meshid = self.new_id("mesh")
- self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">')
+ if (len(vi)>2):
+ #only triangles and above
+ indices.append(vi)
+
+
+ meshid = self.new_id("mesh")
+ self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">')
self.writel(S_GEOM,2,'<mesh>')
@@ -468,6 +628,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 +666,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 +681,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 +811,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 +836,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 +859,19 @@ class DaeExporter:
if (node.parent.type=="ARMATURE"):
armature=node.parent
- meshdata = self.export_mesh(node,armature,shapename)
+ meshdata = self.export_mesh(node,armature)
+ close_controller=False
- if (armature==None):
- self.writel(S_NODES,il,'<instance_geometry url="#'+meshdata["id"]+'">')
- else:
+ 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 +884,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 +923,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 +979,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 +1007,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 +1152,18 @@ class DaeExporter:
- def export_node(self,node,il,shapename=None):
+ def export_node(self,node,il):
if (not self.is_node_valid(node)):
return
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"):
@@ -931,22 +1174,9 @@ class DaeExporter:
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>')
@@ -997,18 +1227,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 +1250,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 +1292,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 +1307,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 +1317,7 @@ class DaeExporter:
tcn = []
xform_cache={}
+ blend_cache={}
# Change frames first, export objects last
# This improves performance enormously
@@ -1081,9 +1332,26 @@ 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:
+ 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 +1368,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,10 +1395,13 @@ 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
@@ -1141,10 +1413,19 @@ class DaeExporter:
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=[]
@@ -1179,12 +1460,19 @@ class DaeExporter:
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 s in 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
else:
self.export_animation(self.scene.frame_start,self.scene.frame_end)
@@ -1207,6 +1495,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 +1554,7 @@ class DaeExporter:
self.skeleton_info={}
self.config=kwargs
self.valid_nodes=[]
+ self.armature_for_morph={}