summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE.md4
-rw-r--r--SConstruct4
-rw-r--r--bin/tests/test_string.cpp137
-rw-r--r--core/bind/core_bind.cpp91
-rw-r--r--core/bind/core_bind.h20
-rw-r--r--core/global_constants.cpp1
-rw-r--r--core/io/file_access_pack.cpp4
-rw-r--r--core/io/file_access_pack.h1
-rw-r--r--core/io/resource_format_binary.cpp10
-rw-r--r--core/io/resource_format_xml.cpp5
-rw-r--r--core/math/camera_matrix.cpp19
-rw-r--r--core/math/geometry.h4
-rw-r--r--core/object.cpp8
-rw-r--r--core/object.h1
-rw-r--r--core/os/dir_access.h1
-rw-r--r--core/os/os.h24
-rw-r--r--core/ustring.cpp79
-rw-r--r--core/ustring.h5
-rw-r--r--core/variant_call.cpp10
-rw-r--r--core/variant_op.cpp19
-rw-r--r--demos/2d/area_input/box_area.pngbin0 -> 1246 bytes
-rw-r--r--demos/2d/area_input/circle_area.pngbin0 -> 3030 bytes
-rw-r--r--demos/2d/area_input/engine.cfg4
-rw-r--r--demos/2d/area_input/input.gd16
-rw-r--r--demos/2d/area_input/input.scnbin0 -> 2886 bytes
-rw-r--r--demos/2d/fog_of_war/.fscache11
-rw-r--r--demos/2d/fog_of_war/engine.cfg12
-rw-r--r--demos/2d/fog_of_war/floor.pngbin0 -> 572 bytes
-rw-r--r--demos/2d/fog_of_war/fog.gd86
-rw-r--r--demos/2d/fog_of_war/fog.pngbin0 -> 31448 bytes
-rw-r--r--demos/2d/fog_of_war/fog.scnbin0 -> 3714 bytes
-rw-r--r--demos/2d/fog_of_war/fog.xml29
-rw-r--r--demos/2d/fog_of_war/icon.pngbin0 -> 8681 bytes
-rw-r--r--demos/2d/fog_of_war/icon.png.flags1
-rw-r--r--demos/2d/fog_of_war/tile_edit.scnbin0 -> 1443 bytes
-rw-r--r--demos/2d/fog_of_war/troll.gd43
-rw-r--r--demos/2d/fog_of_war/troll.pngbin0 -> 7246 bytes
-rw-r--r--demos/2d/fog_of_war/troll.scnbin0 -> 1839 bytes
-rw-r--r--demos/2d/hdr/beach_cave.gd26
-rw-r--r--demos/2d/hdr/beach_cave.scnbin0 -> 2972 bytes
-rw-r--r--demos/2d/hdr/engine.cfg13
-rw-r--r--demos/2d/hdr/ocean_beach.pngbin0 -> 443558 bytes
-rw-r--r--demos/2d/hdr/ocean_beach.png.flags1
-rw-r--r--demos/2d/hdr/ocean_cave.pngbin0 -> 745215 bytes
-rw-r--r--demos/2d/hdr/ocean_cave.png.flags1
-rw-r--r--demos/2d/isometric/dungeon.scnbin4582 -> 4721 bytes
-rw-r--r--demos/2d/isometric_light/character_shder.resbin0 -> 1150 bytes
-rw-r--r--demos/2d/isometric_light/column.scnbin0 -> 1909 bytes
-rw-r--r--demos/2d/isometric_light/cubio.gd96
-rw-r--r--demos/2d/isometric_light/cubio.scnbin0 -> 6927 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0001.pngbin0 -> 7163 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0002.pngbin0 -> 7182 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0003.pngbin0 -> 7173 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0004.pngbin0 -> 7174 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0005.pngbin0 -> 7207 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0006.pngbin0 -> 7302 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0007.pngbin0 -> 7296 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0008.pngbin0 -> 7332 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0009.pngbin0 -> 7320 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0010.pngbin0 -> 7311 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0011.pngbin0 -> 7359 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0012.pngbin0 -> 7392 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0013.pngbin0 -> 7398 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0014.pngbin0 -> 7399 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0015.pngbin0 -> 7340 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0016.pngbin0 -> 7278 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0017.pngbin0 -> 7342 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0018.pngbin0 -> 7370 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0019.pngbin0 -> 7379 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0020.pngbin0 -> 7432 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0021.pngbin0 -> 7391 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0022.pngbin0 -> 7381 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0023.pngbin0 -> 7330 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0024.pngbin0 -> 7363 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0025.pngbin0 -> 7368 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0026.pngbin0 -> 7356 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0027.pngbin0 -> 7358 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0028.pngbin0 -> 7294 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0029.pngbin0 -> 7342 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0030.pngbin0 -> 7402 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0031.pngbin0 -> 7442 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0032.pngbin0 -> 7409 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0033.pngbin0 -> 7407 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0034.pngbin0 -> 7389 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0035.pngbin0 -> 7351 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0036.pngbin0 -> 7348 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0037.pngbin0 -> 7356 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0038.pngbin0 -> 7318 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0039.pngbin0 -> 7366 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0040.pngbin0 -> 7385 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0041.pngbin0 -> 7400 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0042.pngbin0 -> 7397 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0043.pngbin0 -> 7363 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0044.pngbin0 -> 7377 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0045.pngbin0 -> 7368 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0046.pngbin0 -> 7346 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0047.pngbin0 -> 7333 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0048.pngbin0 -> 7305 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0049.pngbin0 -> 7328 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0050.pngbin0 -> 7319 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0051.pngbin0 -> 7256 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0052.pngbin0 -> 7287 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0053.pngbin0 -> 7236 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0054.pngbin0 -> 7182 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0055.pngbin0 -> 7169 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0056.pngbin0 -> 7166 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0057.pngbin0 -> 7146 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0058.pngbin0 -> 7174 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0059.pngbin0 -> 7163 bytes
-rw-r--r--demos/2d/isometric_light/cubio/idle0060.pngbin0 -> 7163 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0001.pngbin0 -> 7027 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0002.pngbin0 -> 7234 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0003.pngbin0 -> 7658 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0004.pngbin0 -> 7999 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0005.pngbin0 -> 8086 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0006.pngbin0 -> 8004 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0007.pngbin0 -> 7759 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0008.pngbin0 -> 7485 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0009.pngbin0 -> 7066 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0010.pngbin0 -> 6925 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0011.pngbin0 -> 7003 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0012.pngbin0 -> 7316 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0013.pngbin0 -> 7607 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0014.pngbin0 -> 7924 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0015.pngbin0 -> 8000 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0016.pngbin0 -> 8025 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0017.pngbin0 -> 7918 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0018.pngbin0 -> 7532 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0019.pngbin0 -> 7247 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-b-0020.pngbin0 -> 7035 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0001.pngbin0 -> 7097 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0002.pngbin0 -> 7074 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0003.pngbin0 -> 7273 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0004.pngbin0 -> 7778 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0005.pngbin0 -> 7717 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0006.pngbin0 -> 8142 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0007.pngbin0 -> 8300 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0008.pngbin0 -> 8653 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0009.pngbin0 -> 8846 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0010.pngbin0 -> 8824 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0011.pngbin0 -> 8848 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0012.pngbin0 -> 8649 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0013.pngbin0 -> 8695 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0014.pngbin0 -> 8435 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0015.pngbin0 -> 8226 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0016.pngbin0 -> 7895 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0017.pngbin0 -> 7712 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0018.pngbin0 -> 7103 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0019.pngbin0 -> 7094 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-bl-0020.pngbin0 -> 7051 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0001.pngbin0 -> 8257 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0002.pngbin0 -> 7883 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0003.pngbin0 -> 6680 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0004.pngbin0 -> 6278 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0005.pngbin0 -> 6348 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0006.pngbin0 -> 5629 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0007.pngbin0 -> 6754 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0008.pngbin0 -> 7612 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0009.pngbin0 -> 8044 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0010.pngbin0 -> 8013 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0011.pngbin0 -> 7917 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0012.pngbin0 -> 7692 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0013.pngbin0 -> 6778 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0014.pngbin0 -> 6176 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0015.pngbin0 -> 6263 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0016.pngbin0 -> 6004 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0017.pngbin0 -> 6483 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0018.pngbin0 -> 7276 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0019.pngbin0 -> 7899 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-l-0020.pngbin0 -> 8119 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0001.pngbin0 -> 7095 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0002.pngbin0 -> 7064 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0003.pngbin0 -> 6854 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0004.pngbin0 -> 6801 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0005.pngbin0 -> 6900 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0006.pngbin0 -> 7017 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0007.pngbin0 -> 7128 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0008.pngbin0 -> 7065 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0009.pngbin0 -> 7000 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0010.pngbin0 -> 6980 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0011.pngbin0 -> 6978 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0012.pngbin0 -> 7139 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0013.pngbin0 -> 7191 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0014.pngbin0 -> 7119 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0015.pngbin0 -> 7051 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0016.pngbin0 -> 6995 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0017.pngbin0 -> 6832 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0018.pngbin0 -> 6962 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0019.pngbin0 -> 7049 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-u-0020.pngbin0 -> 7067 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0001.pngbin0 -> 8202 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0002.pngbin0 -> 8074 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0003.pngbin0 -> 7716 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0004.pngbin0 -> 7587 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0005.pngbin0 -> 7383 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0006.pngbin0 -> 7107 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0007.pngbin0 -> 6671 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0008.pngbin0 -> 6847 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0009.pngbin0 -> 6892 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0010.pngbin0 -> 6858 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0011.pngbin0 -> 7067 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0012.pngbin0 -> 6985 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0013.pngbin0 -> 6600 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0014.pngbin0 -> 7104 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0015.pngbin0 -> 7320 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0016.pngbin0 -> 7478 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0017.pngbin0 -> 7736 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0018.pngbin0 -> 7960 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0019.pngbin0 -> 7982 bytes
-rw-r--r--demos/2d/isometric_light/cubio/norm-ul-0020.pngbin0 -> 8137 bytes
-rw-r--r--demos/2d/isometric_light/energy.pngbin0 -> 6968 bytes
-rw-r--r--demos/2d/isometric_light/engine.cfg18
-rw-r--r--demos/2d/isometric_light/export.cfg262
-rw-r--r--demos/2d/isometric_light/faceColor.pngbin0 -> 47941 bytes
-rw-r--r--demos/2d/isometric_light/faceMask.pngbin0 -> 3106 bytes
-rw-r--r--demos/2d/isometric_light/faceNormal.pngbin0 -> 54844 bytes
-rw-r--r--demos/2d/isometric_light/fire.pngbin0 -> 8116 bytes
-rw-r--r--demos/2d/isometric_light/floor_shader.resbin0 -> 1026 bytes
-rw-r--r--demos/2d/isometric_light/light2.pngbin0 -> 3500 bytes
-rw-r--r--demos/2d/isometric_light/map.gd18
-rw-r--r--demos/2d/isometric_light/map.scnbin0 -> 8535 bytes
-rw-r--r--demos/2d/isometric_light/shadow_blob.pngbin0 -> 884 bytes
-rw-r--r--demos/2d/isometric_light/shoot.gd27
-rw-r--r--demos/2d/isometric_light/shoot.scnbin0 -> 4561 bytes
-rw-r--r--demos/2d/isometric_light/shoot_halo.pngbin0 -> 91312 bytes
-rw-r--r--demos/2d/isometric_light/tileset.resbin0 -> 2775 bytes
-rw-r--r--demos/2d/isometric_light/tileset_scene.scnbin0 -> 4812 bytes
-rw-r--r--demos/2d/isometric_light/torch.scnbin0 -> 4262 bytes
-rw-r--r--demos/2d/isometric_light/torch_light.pngbin0 -> 1262 bytes
-rw-r--r--demos/2d/isometric_light/torch_shader.resbin0 -> 741 bytes
-rw-r--r--demos/2d/isometric_light/wall_shader.resbin0 -> 1684 bytes
-rw-r--r--demos/2d/platformer/stage.xml35
-rw-r--r--demos/2d/screen_space_shaders/art/burano.jpgbin0 -> 246589 bytes
-rw-r--r--demos/2d/screen_space_shaders/art/burano.pngbin0 -> 974437 bytes
-rw-r--r--demos/2d/screen_space_shaders/art/filmgrain.pngbin0 -> 290595 bytes
-rw-r--r--demos/2d/screen_space_shaders/art/filmgrain.png.flags1
-rw-r--r--demos/2d/screen_space_shaders/art/forest.pngbin0 -> 1199433 bytes
-rw-r--r--demos/2d/screen_space_shaders/art/mountains.pngbin0 -> 927435 bytes
-rw-r--r--demos/2d/screen_space_shaders/art/platformer.pngbin0 -> 44102 bytes
-rw-r--r--demos/2d/screen_space_shaders/art/vignette.pngbin0 -> 4075 bytes
-rw-r--r--demos/2d/screen_space_shaders/art/white.pngbin0 -> 174 bytes
-rw-r--r--demos/2d/screen_space_shaders/engine.cfg4
-rw-r--r--demos/2d/screen_space_shaders/screen_shaders.gd32
-rw-r--r--demos/2d/screen_space_shaders/screen_shaders.scnbin0 -> 5762 bytes
-rw-r--r--demos/2d/sdf_font/KaushanScript-Regular.otfbin0 -> 89168 bytes
-rw-r--r--demos/2d/sdf_font/engine.cfg4
-rw-r--r--demos/2d/sdf_font/font.fntbin0 -> 180332 bytes
-rw-r--r--demos/2d/sdf_font/sdf.scnbin0 -> 2415 bytes
-rw-r--r--demos/2d/sprite_shaders/cubio.pngbin0 -> 26579 bytes
-rw-r--r--demos/2d/sprite_shaders/engine.cfg4
-rw-r--r--demos/2d/sprite_shaders/sprite_shaders.scnbin0 -> 4079 bytes
-rw-r--r--demos/2d/texscreen/bubble.pngbin0 -> 18619 bytes
-rw-r--r--demos/2d/texscreen/bubbles.gd17
-rw-r--r--demos/2d/texscreen/bubbles.scnbin0 -> 1456 bytes
-rw-r--r--demos/2d/texscreen/burano.pngbin0 -> 974437 bytes
-rw-r--r--demos/2d/texscreen/engine.cfg4
-rw-r--r--demos/2d/texscreen/lens.gd37
-rw-r--r--demos/2d/texscreen/lens.scnbin0 -> 1805 bytes
-rw-r--r--demos/3d/kinematic_char/cubelib.resbin11431 -> 11530 bytes
-rw-r--r--demos/3d/kinematic_char/level.scnbin15323 -> 15556 bytes
-rw-r--r--demos/gui/drag_and_drop/drag_and_drop.scnbin0 -> 2594 bytes
-rw-r--r--demos/gui/drag_and_drop/drag_drop_script.gd24
-rw-r--r--demos/gui/drag_and_drop/engine.cfg4
-rw-r--r--demos/misc/window_management/control.gd177
-rw-r--r--demos/misc/window_management/engine.cfg19
-rw-r--r--demos/misc/window_management/icon.pngbin0 -> 3639 bytes
-rw-r--r--demos/misc/window_management/icon.png.flags1
-rw-r--r--demos/misc/window_management/observer/observer.gd79
-rw-r--r--demos/misc/window_management/observer/observer.scnbin0 -> 1786 bytes
-rw-r--r--demos/misc/window_management/window_management.scnbin0 -> 5087 bytes
-rw-r--r--demos/viewport/gui_in_3d/gui_3d.gd49
-rw-r--r--demos/viewport/gui_in_3d/gui_3d.scnbin3498 -> 4668 bytes
-rw-r--r--doc/base/classes.xml32
-rw-r--r--drivers/SCsub1
-rw-r--r--drivers/etc1/rg_etc1.cpp2
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp799
-rw-r--r--drivers/gles2/rasterizer_gles2.h66
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp25
-rw-r--r--drivers/gles2/shaders/SCsub1
-rw-r--r--drivers/gles2/shaders/canvas.glsl157
-rw-r--r--drivers/gles2/shaders/canvas_shadow.glsl62
-rw-r--r--drivers/trex/trex.c2
-rw-r--r--drivers/unix/dir_access_unix.cpp6
-rw-r--r--drivers/unix/dir_access_unix.h2
-rw-r--r--drivers/unix/file_access_unix.cpp2
-rw-r--r--drivers/vorbis/codebook.c2
-rw-r--r--drivers/vorbis/floor1.c2
-rw-r--r--drivers/windows/dir_access_windows.cpp11
-rw-r--r--drivers/windows/dir_access_windows.h1
-rw-r--r--drivers/windows/file_access_windows.cpp24
-rwxr-xr-xmethods.py8
-rw-r--r--modules/gdscript/gd_functions.cpp2
-rw-r--r--modules/gdscript/gd_script.cpp8
-rw-r--r--modules/gridmap/grid_map.cpp3
-rw-r--r--platform/android/AndroidManifest.xml.template3
-rw-r--r--platform/android/SCsub2
-rw-r--r--platform/android/audio_driver_opensl.cpp8
-rw-r--r--platform/android/dir_access_android.cpp3
-rw-r--r--platform/android/dir_access_android.h1
-rw-r--r--platform/android/dir_access_jandroid.cpp3
-rw-r--r--platform/android/java_glue.cpp113
-rw-r--r--platform/android/os_android.cpp2
-rw-r--r--platform/bb10/SCsub10
-rw-r--r--platform/bb10/bar/bar-descriptor.xml30
-rw-r--r--platform/bb10/detect.py2
-rw-r--r--platform/bb10/export/export.cpp79
-rw-r--r--platform/bb10/os_bb10.cpp2
-rwxr-xr-xplatform/iphone/gl_view.h2
-rwxr-xr-xplatform/iphone/gl_view.mm52
-rw-r--r--platform/windows/detect.py212
-rw-r--r--platform/windows/os_windows.cpp12
-rw-r--r--platform/x11/detect.py10
-rw-r--r--platform/x11/os_x11.cpp485
-rw-r--r--platform/x11/os_x11.h30
-rw-r--r--scene/2d/area_2d.cpp261
-rw-r--r--scene/2d/area_2d.h37
-rw-r--r--scene/2d/back_buffer_copy.cpp75
-rw-r--r--scene/2d/back_buffer_copy.h41
-rw-r--r--scene/2d/camera_2d.cpp11
-rw-r--r--scene/2d/camera_2d.h189
-rw-r--r--scene/2d/canvas_item.cpp343
-rw-r--r--scene/2d/canvas_item.h60
-rw-r--r--scene/2d/collision_object_2d.cpp71
-rw-r--r--scene/2d/collision_object_2d.h12
-rw-r--r--scene/2d/light_2d.cpp92
-rw-r--r--scene/2d/light_2d.h16
-rw-r--r--scene/2d/light_occluder_2d.cpp202
-rw-r--r--scene/2d/light_occluder_2d.h73
-rw-r--r--scene/2d/node_2d.cpp49
-rw-r--r--scene/2d/node_2d.h8
-rw-r--r--scene/2d/particles_2d.cpp5
-rw-r--r--scene/2d/physics_body_2d.cpp1
-rw-r--r--scene/2d/tile_map.cpp309
-rw-r--r--scene/2d/tile_map.h41
-rw-r--r--scene/2d/visibility_notifier_2d.cpp22
-rw-r--r--scene/2d/visibility_notifier_2d.h1
-rw-r--r--scene/3d/camera.cpp24
-rw-r--r--scene/3d/camera.h2
-rw-r--r--scene/3d/spatial.cpp113
-rw-r--r--scene/3d/spatial.h15
-rw-r--r--scene/3d/visual_instance.cpp15
-rw-r--r--scene/3d/visual_instance.h4
-rw-r--r--scene/gui/base_button.cpp5
-rw-r--r--scene/gui/check_box.cpp79
-rw-r--r--scene/gui/check_box.h55
-rw-r--r--scene/gui/color_picker.cpp1
-rw-r--r--scene/gui/control.cpp84
-rw-r--r--scene/gui/file_dialog.cpp19
-rw-r--r--scene/gui/label.cpp4
-rw-r--r--scene/gui/text_edit.cpp53
-rw-r--r--scene/main/viewport.cpp71
-rw-r--r--scene/main/viewport.h1
-rw-r--r--scene/register_scene_types.cpp10
-rw-r--r--scene/resources/default_theme/default_theme.cpp38
-rw-r--r--scene/resources/default_theme/radio_checked.pngbin0 -> 569 bytes
-rw-r--r--scene/resources/default_theme/radio_unchecked.pngbin0 -> 421 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h10
-rw-r--r--scene/resources/environment.cpp7
-rw-r--r--scene/resources/environment.h6
-rw-r--r--scene/resources/font.cpp21
-rw-r--r--scene/resources/font.h4
-rw-r--r--scene/resources/texture.cpp9
-rw-r--r--scene/resources/texture.h2
-rw-r--r--scene/resources/tile_set.cpp106
-rw-r--r--scene/resources/tile_set.h22
-rw-r--r--scene/resources/world.cpp6
-rw-r--r--scene/resources/world.h2
-rw-r--r--scene/resources/world_2d.cpp9
-rw-r--r--scene/resources/world_2d.h4
-rw-r--r--scene/scene_string_names.cpp7
-rw-r--r--scene/scene_string_names.h8
-rw-r--r--servers/physics/body_sw.cpp2
-rw-r--r--servers/physics/shape_sw.h2
-rw-r--r--servers/physics/space_sw.cpp2
-rw-r--r--servers/physics_2d/area_2d_sw.cpp71
-rw-r--r--servers/physics_2d/area_2d_sw.h34
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp69
-rw-r--r--servers/physics_2d/area_pair_2d_sw.h18
-rw-r--r--servers/physics_2d/body_2d_sw.cpp2
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp1
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h4
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp33
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h6
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp63
-rw-r--r--servers/physics_2d/shape_2d_sw.h10
-rw-r--r--servers/physics_2d/space_2d_sw.cpp66
-rw-r--r--servers/physics_2d/space_2d_sw.h1
-rw-r--r--servers/physics_2d_server.cpp31
-rw-r--r--servers/physics_2d_server.h9
-rw-r--r--servers/visual/rasterizer.cpp2
-rw-r--r--servers/visual/rasterizer.h81
-rw-r--r--servers/visual/shader_language.cpp55
-rw-r--r--servers/visual/shader_language.h2
-rw-r--r--servers/visual/visual_server_raster.cpp534
-rw-r--r--servers/visual/visual_server_raster.h73
-rw-r--r--servers/visual/visual_server_wrap_mt.h34
-rw-r--r--servers/visual_server.h42
-rw-r--r--tools/collada/collada.cpp2
-rw-r--r--tools/collada/collada.h18
-rw-r--r--tools/editor/connections_dialog.cpp11
-rw-r--r--tools/editor/editor_dir_dialog.cpp22
-rw-r--r--tools/editor/editor_import_export.cpp30
-rw-r--r--tools/editor/editor_import_export.h3
-rw-r--r--tools/editor/editor_node.cpp7
-rw-r--r--tools/editor/editor_settings.cpp1
-rw-r--r--tools/editor/icons/icon_back_buffer_copy.pngbin0 -> 204 bytes
-rw-r--r--tools/editor/icons/icon_canvas_item_material.pngbin0 -> 835 bytes
-rw-r--r--tools/editor/icons/icon_canvas_modulate.pngbin0 -> 441 bytes
-rw-r--r--tools/editor/icons/icon_check_box.pngbin0 -> 344 bytes
-rw-r--r--tools/editor/icons/icon_light_occluder_2d.pngbin0 -> 516 bytes
-rw-r--r--tools/editor/icons/icon_occluder_polygon_2d.pngbin0 -> 581 bytes
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.cpp347
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp65
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp2
-rw-r--r--tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/light_occluder_2d_editor_plugin.cpp502
-rw-r--r--tools/editor/plugins/light_occluder_2d_editor_plugin.h87
-rw-r--r--tools/editor/plugins/navigation_polygon_editor_plugin.cpp6
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp12
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp71
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.h2
-rw-r--r--tools/editor/plugins/theme_editor_plugin.cpp20
-rw-r--r--tools/editor/plugins/theme_editor_plugin.h2
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.cpp40
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.cpp170
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.h2
-rw-r--r--tools/editor/property_editor.cpp66
-rw-r--r--tools/export/blender25/io_scene_dae/export_dae.py67
-rw-r--r--tools/script_plugins/time/time.gd4
429 files changed, 8267 insertions, 1157 deletions
diff --git a/LICENSE.md b/LICENSE.md
index 122736f5f1..ca0a9702f7 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -21,3 +21,7 @@
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+**********************************************************************
+
diff --git a/SConstruct b/SConstruct
index c68ca3989f..2dc9fa1e70 100644
--- a/SConstruct
+++ b/SConstruct
@@ -67,12 +67,16 @@ env_base.android_source_modules=[]
env_base.android_source_files=[]
env_base.android_module_libraries=[]
env_base.android_manifest_chunk=""
+env_base.android_permission_chunk=""
+env_base.android_appattributes_chunk=""
env_base.disabled_modules=[]
env_base.__class__.android_module_source = methods.android_module_source
env_base.__class__.android_module_library = methods.android_module_library
env_base.__class__.android_module_file = methods.android_module_file
env_base.__class__.android_module_manifest = methods.android_module_manifest
+env_base.__class__.android_module_permission = methods.android_module_permission
+env_base.__class__.android_module_attribute = methods.android_module_attribute
env_base.__class__.disable_module = methods.disable_module
env_base.__class__.add_source_files = methods.add_source_files
diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp
index 4aaddd8ac1..2a048f2f67 100644
--- a/bin/tests/test_string.cpp
+++ b/bin/tests/test_string.cpp
@@ -519,12 +519,13 @@ bool test_28() {
char output_format[] = "\tTest:\t%ls => %ls (%s)\n";
String format, output;
Array args;
+ bool error;
// %%
format = "fish %% frog";
args.clear();
- output = format.sprintf(args);
- success = (output == String("fish % frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish % frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -534,8 +535,8 @@ bool test_28() {
format = "fish %d frog";
args.clear();
args.push_back(5);
- output = format.sprintf(args);
- success = (output == String("fish 5 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 5 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -543,8 +544,8 @@ bool test_28() {
format = "fish %05d frog";
args.clear();
args.push_back(5);
- output = format.sprintf(args);
- success = (output == String("fish 00005 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 00005 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -552,8 +553,8 @@ bool test_28() {
format = "fish %5d frog";
args.clear();
args.push_back(5);
- output = format.sprintf(args);
- success = (output == String("fish 5 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 5 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -561,8 +562,8 @@ bool test_28() {
format = "fish %-5d frog";
args.clear();
args.push_back(5);
- output = format.sprintf(args);
- success = (output == String("fish 5 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 5 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -570,8 +571,8 @@ bool test_28() {
format = "fish %+d frog";
args.clear();
args.push_back(5);
- output = format.sprintf(args);
- success = (output == String("fish +5 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish +5 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -579,8 +580,8 @@ bool test_28() {
format = "fish %d frog";
args.clear();
args.push_back(-5);
- output = format.sprintf(args);
- success = (output == String("fish -5 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish -5 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -588,8 +589,8 @@ bool test_28() {
format = "fish %x frog";
args.clear();
args.push_back(45);
- output = format.sprintf(args);
- success = (output == String("fish 2d frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 2d frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -597,8 +598,8 @@ bool test_28() {
format = "fish %X frog";
args.clear();
args.push_back(45);
- output = format.sprintf(args);
- success = (output == String("fish 2D frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 2D frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -606,8 +607,8 @@ bool test_28() {
format = "fish %o frog";
args.clear();
args.push_back(99);
- output = format.sprintf(args);
- success = (output == String("fish 143 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 143 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -617,8 +618,8 @@ bool test_28() {
format = "fish %f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish 99.990000 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 99.990000 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -626,8 +627,8 @@ bool test_28() {
format = "fish %11f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish 99.990000 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 99.990000 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -635,8 +636,8 @@ bool test_28() {
format = "fish %-11f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish 99.990000 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 99.990000 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -644,8 +645,8 @@ bool test_28() {
format = "fish %f frog";
args.clear();
args.push_back(99);
- output = format.sprintf(args);
- success = (output == String("fish 99.000000 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 99.000000 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -653,8 +654,8 @@ bool test_28() {
format = "fish %+f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish +99.990000 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish +99.990000 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -662,8 +663,8 @@ bool test_28() {
format = "fish %.1f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish 100.0 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 100.0 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -671,8 +672,8 @@ bool test_28() {
format = "fish %.12f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish 99.990000000000 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 99.990000000000 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -680,8 +681,8 @@ bool test_28() {
format = "fish %.f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish 100 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 100 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -691,8 +692,8 @@ bool test_28() {
format = "fish %s frog";
args.clear();
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == String("fish cheese frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish cheese frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -700,8 +701,8 @@ bool test_28() {
format = "fish %10s frog";
args.clear();
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == String("fish cheese frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish cheese frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -709,8 +710,8 @@ bool test_28() {
format = "fish %-10s frog";
args.clear();
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == String("fish cheese frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish cheese frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -720,8 +721,8 @@ bool test_28() {
format = "fish %c frog";
args.clear();
args.push_back("A");
- output = format.sprintf(args);
- success = (output == String("fish A frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish A frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -729,8 +730,8 @@ bool test_28() {
format = "fish %c frog";
args.clear();
args.push_back(65);
- output = format.sprintf(args);
- success = (output == String("fish A frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish A frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -741,8 +742,8 @@ bool test_28() {
args.clear();
args.push_back(10);
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == String("fish cheese frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish cheese frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -751,8 +752,8 @@ bool test_28() {
args.clear();
args.push_back(10);
args.push_back(99);
- output = format.sprintf(args);
- success = (output == String("fish 99 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 99 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -762,8 +763,8 @@ bool test_28() {
args.push_back(10);
args.push_back(3);
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == String("fish 99.990 frog"));
+ output = format.sprintf(args, &error);
+ success = (output == String("fish 99.990 frog") && !error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -773,8 +774,8 @@ bool test_28() {
format = "fish %s %s frog";
args.clear();
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "not enough arguments for format string" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -783,8 +784,8 @@ bool test_28() {
args.clear();
args.push_back("hello");
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "not all arguments converted during string formatting" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -792,8 +793,8 @@ bool test_28() {
format = "fish %10";
args.clear();
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "incomplete format" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -801,8 +802,8 @@ bool test_28() {
format = "fish %&f frog";
args.clear();
args.push_back("cheese");
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "unsupported format character" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -810,8 +811,8 @@ bool test_28() {
format = "fish %2.2.2f frog";
args.clear();
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "too many decimal points in format" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -820,8 +821,8 @@ bool test_28() {
args.clear();
args.push_back("cheese");
args.push_back(99.99);
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "* wants number" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -829,8 +830,8 @@ bool test_28() {
format = "fish %c frog";
args.clear();
args.push_back("sc");
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "%c requires number or single-character string" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
@@ -838,8 +839,8 @@ bool test_28() {
format = "fish %c frog";
args.clear();
args.push_back(Array());
- output = format.sprintf(args);
- success = (output == "");
+ output = format.sprintf(args, &error);
+ success = (output == "%c requires number or single-character string" && error);
OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
if (!success) state = false;
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 8d18acdc23..858f5cec27 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -176,6 +176,76 @@ bool _OS::is_video_mode_fullscreen(int p_screen) const {
}
+#ifdef NEW_WM_API
+int _OS::get_screen_count() const {
+ return OS::get_singleton()->get_screen_count();
+}
+
+int _OS::get_screen() const {
+ return OS::get_singleton()->get_screen();
+}
+
+void _OS::set_screen(int p_screen) {
+ OS::get_singleton()->set_screen(p_screen);
+}
+
+Point2 _OS::get_screen_position(int p_screen) const {
+ return OS::get_singleton()->get_screen_position(p_screen);
+}
+
+Size2 _OS::get_screen_size(int p_screen) const {
+ return OS::get_singleton()->get_screen_size(p_screen);
+}
+
+Point2 _OS::get_window_position() const {
+ return OS::get_singleton()->get_window_position();
+}
+
+void _OS::set_window_position(const Point2& p_position) {
+ OS::get_singleton()->set_window_position(p_position);
+}
+
+Size2 _OS::get_window_size() const {
+ return OS::get_singleton()->get_window_size();
+}
+
+void _OS::set_window_size(const Size2& p_size) {
+ OS::get_singleton()->set_window_size(p_size);
+}
+
+void _OS::set_fullscreen(bool p_enabled) {
+ OS::get_singleton()->set_fullscreen(p_enabled);
+}
+
+bool _OS::is_fullscreen() const {
+ return OS::get_singleton()->is_fullscreen();
+}
+
+void _OS::set_resizable(bool p_enabled) {
+ OS::get_singleton()->set_resizable(p_enabled);
+}
+
+bool _OS::is_resizable() const {
+ return OS::get_singleton()->is_resizable();
+}
+
+void _OS::set_minimized(bool p_enabled) {
+ OS::get_singleton()->set_minimized(p_enabled);
+}
+
+bool _OS::is_minimized() const {
+ return OS::get_singleton()->is_minimized();
+}
+
+void _OS::set_maximized(bool p_enabled) {
+ OS::get_singleton()->set_maximized(p_enabled);
+}
+
+bool _OS::is_maximized() const {
+ return OS::get_singleton()->is_maximized();
+}
+#endif
+
void _OS::set_use_file_access_save_and_swap(bool p_enable) {
FileAccess::set_backup_save(p_enable);
@@ -186,7 +256,6 @@ bool _OS::is_video_mode_resizable(int p_screen) const {
OS::VideoMode vm;
vm = OS::get_singleton()->get_video_mode(p_screen);
return vm.resizable;
-
}
Array _OS::get_fullscreen_mode_list(int p_screen) const {
@@ -637,6 +706,26 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
+#ifdef NEW_WM_API
+ ObjectTypeDB::bind_method(_MD("get_screen_count"),&_OS::get_screen_count);
+ ObjectTypeDB::bind_method(_MD("get_screen"),&_OS::get_screen);
+ ObjectTypeDB::bind_method(_MD("set_screen"),&_OS::set_screen);
+ ObjectTypeDB::bind_method(_MD("get_screen_position"),&_OS::get_screen_position,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_screen_size"),&_OS::get_screen_size,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_window_position"),&_OS::get_window_position);
+ ObjectTypeDB::bind_method(_MD("set_window_position"),&_OS::set_window_position);
+ ObjectTypeDB::bind_method(_MD("get_window_size"),&_OS::get_window_size);
+ ObjectTypeDB::bind_method(_MD("set_window_size"),&_OS::set_window_size);
+ ObjectTypeDB::bind_method(_MD("set_fullscreen","enabled"),&_OS::set_fullscreen);
+ ObjectTypeDB::bind_method(_MD("is_fullscreen"),&_OS::is_fullscreen);
+ ObjectTypeDB::bind_method(_MD("set_resizable","enabled"),&_OS::set_resizable);
+ ObjectTypeDB::bind_method(_MD("is_resizable"),&_OS::is_resizable);
+ ObjectTypeDB::bind_method(_MD("set_minimized", "enabled"),&_OS::set_minimized);
+ ObjectTypeDB::bind_method(_MD("is_minimized"),&_OS::is_minimized);
+ ObjectTypeDB::bind_method(_MD("set_maximized", "enabled"),&_OS::set_maximized);
+ ObjectTypeDB::bind_method(_MD("is_maximized"),&_OS::is_maximized);
+#endif
+
ObjectTypeDB::bind_method(_MD("set_iterations_per_second","iterations_per_second"),&_OS::set_iterations_per_second);
ObjectTypeDB::bind_method(_MD("get_iterations_per_second"),&_OS::get_iterations_per_second);
ObjectTypeDB::bind_method(_MD("set_target_fps","target_fps"),&_OS::set_target_fps);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 057ad90fe9..1a80e35221 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -108,6 +108,26 @@ public:
bool is_video_mode_resizable(int p_screen=0) const;
Array get_fullscreen_mode_list(int p_screen=0) const;
+#ifdef NEW_WM_API
+ virtual int get_screen_count() const;
+ virtual int get_screen() const;
+ virtual void set_screen(int p_screen);
+ virtual Point2 get_screen_position(int p_screen=0) const;
+ virtual Size2 get_screen_size(int p_screen=0) const;
+ virtual Point2 get_window_position() const;
+ virtual void set_window_position(const Point2& p_position);
+ virtual Size2 get_window_size() const;
+ virtual void set_window_size(const Size2& p_size);
+ virtual void set_fullscreen(bool p_enabled);
+ virtual bool is_fullscreen() const;
+ virtual void set_resizable(bool p_enabled);
+ virtual bool is_resizable() const;
+ virtual void set_minimized(bool p_enabled);
+ virtual bool is_minimized() const;
+ virtual void set_maximized(bool p_enabled);
+ virtual bool is_maximized() const;
+#endif
+
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
bool native_video_is_playing();
void native_video_pause();
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index ae4abc627d..fc48a105db 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -313,6 +313,7 @@ static _GlobalConstant _global_constants[]={
BIND_GLOBAL_CONSTANT( KEY_MASK_ALT ),
BIND_GLOBAL_CONSTANT( KEY_MASK_META ),
BIND_GLOBAL_CONSTANT( KEY_MASK_CTRL ),
+ BIND_GLOBAL_CONSTANT( KEY_MASK_CMD ),
BIND_GLOBAL_CONSTANT( KEY_MASK_KPAD ),
BIND_GLOBAL_CONSTANT( KEY_MASK_GROUP_SWITCH ),
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 6e03819aac..afbd7e3d46 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -362,6 +362,10 @@ bool DirAccessPack::current_is_dir() const{
return cdir;
}
+bool DirAccessPack::current_is_hidden() const{
+
+ return false;
+}
void DirAccessPack::list_dir_end() {
list_dirs.clear();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 5fcc79aaf4..2d0cf5b32e 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -208,6 +208,7 @@ public:
virtual bool list_dir_begin();
virtual String get_next();
virtual bool current_is_dir() const;
+ virtual bool current_is_hidden() const;
virtual void list_dir_end();
virtual int get_drive_count();
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index e2371fe24f..ead6984650 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1778,6 +1778,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
f->store_32(VERSION_MINOR);
f->store_32(FORMAT_VERSION);
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
save_unicode_string(p_resource->get_type());
uint64_t md_at = f->get_pos();
@@ -1910,6 +1915,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
f->store_buffer((const uint8_t*)"RSRC",4); //magic at end
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
f->close();
diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp
index 75384d4ab6..033b4d5e5a 100644
--- a/core/io/resource_format_xml.cpp
+++ b/core/io/resource_format_xml.cpp
@@ -2592,6 +2592,11 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
}
exit_tag("resource_file");
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
f->close();
//memdelete(f);
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index a60dea7379..fbe5f8c741 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -121,7 +121,7 @@ void CameraMatrix::set_orthogonal(float p_size, float p_aspect, float p_znear, f
void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, float p_top, float p_near, float p_far) {
-
+#if 0
///@TODO, give a check to this. I'm not sure if it's working.
set_identity();
@@ -133,10 +133,27 @@ void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, floa
matrix[2][3]=-(2*p_far*p_near) / (p_far-p_near);
matrix[3][2]=-1;
matrix[3][3]=0;
+#else
+ float *te = &matrix[0][0];
+ float x = 2 * p_near / ( p_right - p_left );
+ float y = 2 * p_near / ( p_top - p_bottom );
+
+ float a = ( p_right + p_left ) / ( p_right - p_left );
+ float b = ( p_top + p_bottom ) / ( p_top - p_bottom );
+ float c = - ( p_far + p_near ) / ( p_far - p_near );
+ float d = - 2 * p_far * p_near / ( p_far - p_near );
+
+ te[0] = x; te[4] = 0; te[8] = a; te[12] = 0;
+ te[1] = 0; te[5] = y; te[9] = b; te[13] = 0;
+ te[2] = 0; te[6] = 0; te[10] = c; te[14] = d;
+ te[3] = 0; te[7] = 0; te[11] = - 1; te[15] = 0;
+
+#endif
}
+
float CameraMatrix::get_z_far() const {
const float * matrix = (const float*)this->matrix;
diff --git a/core/math/geometry.h b/core/math/geometry.h
index 7e0cc01a22..4ad4db8523 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -519,9 +519,9 @@ public:
bool s_ab = (b.x-a.x)*as_y-(b.y-a.y)*as_x > 0;
- if((c.x-a.x)*as_y-(c.y-a.y)*as_x > 0 == s_ab) return false;
+ if(((c.x-a.x)*as_y-(c.y-a.y)*as_x > 0) == s_ab) return false;
- if((c.x-b.x)*(s.y-b.y)-(c.y-b.y)*(s.x-b.x) > 0 != s_ab) return false;
+ if(((c.x-b.x)*(s.y-b.y)-(c.y-b.y)*(s.x-b.x) > 0) != s_ab) return false;
return true;
}
diff --git a/core/object.cpp b/core/object.cpp
index 82144ab4be..2b83f728d1 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1033,6 +1033,13 @@ void Object::add_user_signal(const MethodInfo& p_signal) {
signal_map[p_signal.name]=s;
}
+bool Object::_has_user_signal(const StringName& p_name) const {
+
+ if (!signal_map.has(p_name))
+ return false;
+ return signal_map[p_name].user.name.length()>0;
+}
+
struct _ObjectSignalDisconnectData {
StringName signal;
@@ -1431,6 +1438,7 @@ void Object::_bind_methods() {
// ObjectTypeDB::bind_method(_MD("call_deferred","method","arg1","arg2","arg3","arg4"),&Object::_call_deferred_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("add_user_signal","signal","arguments"),&Object::_add_user_signal,DEFVAL(Array()));
+ ObjectTypeDB::bind_method(_MD("has_user_signal","signal"),&Object::_has_user_signal);
// ObjectTypeDB::bind_method(_MD("emit_signal","signal","arguments"),&Object::_emit_signal,DEFVAL(Array()));
diff --git a/core/object.h b/core/object.h
index 97ca50cb1a..eb885f5d20 100644
--- a/core/object.h
+++ b/core/object.h
@@ -386,6 +386,7 @@ friend void postinitialize_handler(Object*);
Dictionary metadata;
void _add_user_signal(const String& p_name, const Array& p_pargs=Array());
+ bool _has_user_signal(const StringName& p_name) const;
Variant _emit_signal(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
Array _get_signal_list() const;
Array _get_signal_connection_list(const String& p_signal) const;
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index d8672218bd..dc56f2308e 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -78,6 +78,7 @@ public:
virtual String get_next(bool* p_is_dir); // compatibility
virtual String get_next()=0;
virtual bool current_is_dir() const=0;
+ virtual bool current_is_hidden() const=0;
virtual void list_dir_end()=0; ///<
diff --git a/core/os/os.h b/core/os/os.h
index d4deff2f5e..6301bd495f 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -73,7 +73,7 @@ public:
bool fullscreen;
bool resizable;
float get_aspect() const { return (float)width/(float)height; }
- VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) { width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
+ VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) {width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
};
protected:
friend class Main;
@@ -149,7 +149,27 @@ public:
virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0)=0;
virtual VideoMode get_video_mode(int p_screen=0) const=0;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const=0;
-
+
+#ifdef NEW_WM_API
+ virtual int get_screen_count() const=0;
+ virtual int get_screen() const=0;
+ virtual void set_screen(int p_screen)=0;
+ virtual Point2 get_screen_position(int p_screen=0) const=0;
+ virtual Size2 get_screen_size(int p_screen=0) const=0;
+ virtual Point2 get_window_position() const=0;
+ virtual void set_window_position(const Point2& p_position)=0;
+ virtual Size2 get_window_size() const=0;
+ virtual void set_window_size(const Size2 p_size)=0;
+ virtual void set_fullscreen(bool p_enabled)=0;
+ virtual bool is_fullscreen() const=0;
+ virtual void set_resizable(bool p_enabled)=0;
+ virtual bool is_resizable() const=0;
+ virtual void set_minimized(bool p_enabled)=0;
+ virtual bool is_minimized() const=0;
+ virtual void set_maximized(bool p_enabled)=0;
+ virtual bool is_maximized() const=0;
+#endif
+
virtual void set_iterations_per_second(int p_ips);
virtual int get_iterations_per_second() const;
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 476ab3f936..497e8f29ed 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -482,7 +482,7 @@ void String::erase(int p_pos, int p_chars) {
String String::capitalize() const {
- String aux=this->replace("_"," ").to_lower();
+ String aux=this->camelcase_to_underscore().replace("_"," ").to_lower();
String cap;
for (int i=0;i<aux.get_slice_count(" ");i++) {
@@ -498,6 +498,29 @@ String String::capitalize() const {
return cap;
}
+
+
+String String::camelcase_to_underscore() const {
+ const CharType * cstr = c_str();
+ String newString;
+ const char A = 'A', Z = 'Z';
+ int startIndex = 0;
+
+ for ( int i = 1; i < this->size()-1; i++ ) {
+ bool isCapital = cstr[i] >= A && cstr[i] <= Z;
+
+ if ( isCapital ) {
+ newString += "_" + this->substr(startIndex, i-startIndex);
+ startIndex = i;
+ }
+ }
+
+ newString += "_" + this->substr(startIndex, this->size()-startIndex);
+
+ return newString;
+}
+
+
int String::get_slice_count(String p_splitter) const{
if (empty())
@@ -3550,8 +3573,8 @@ String String::lpad(int min_length, const String& character) const {
// sprintf is implemented in GDScript via:
// "fish %s pie" % "frog"
// "fish %s %d pie" % ["frog", 12]
-String String::sprintf(const Array& values) const {
-
+// In case of an error, the string returned is the error description and "error" is true.
+String String::sprintf(const Array& values, bool* error) const {
String formatted;
CharType* self = (CharType*)c_str();
int num_items = values.size();
@@ -3564,6 +3587,7 @@ String String::sprintf(const Array& values) const {
bool left_justified;
bool show_sign;
+ *error = true;
for (; *self; self++) {
const CharType c = *self;
@@ -3580,13 +3604,11 @@ String String::sprintf(const Array& values) const {
case 'x': // Hexadecimal (lowercase)
case 'X': { // Hexadecimal (uppercase)
if (value_index >= values.size()) {
- ERR_EXPLAIN("not enough arguments for format string");
- ERR_FAIL_V("");
+ return "not enough arguments for format string";
}
if (!values[value_index].is_num()) {
- ERR_EXPLAIN("a number is required");
- ERR_FAIL_V("");
+ return "a number is required";
}
int64_t value = values[value_index];
@@ -3622,13 +3644,11 @@ String String::sprintf(const Array& values) const {
}
case 'f': { // Float
if (value_index >= values.size()) {
- ERR_EXPLAIN("not enough arguments for format string");
- ERR_FAIL_V("");
+ return "not enough arguments for format string";
}
if (!values[value_index].is_num()) {
- ERR_EXPLAIN("a number is required");
- ERR_FAIL_V("");
+ return "a number is required";
}
double value = values[value_index];
@@ -3657,8 +3677,7 @@ String String::sprintf(const Array& values) const {
}
case 's': { // String
if (value_index >= values.size()) {
- ERR_EXPLAIN("not enough arguments for format string");
- ERR_FAIL_V("");
+ return "not enough arguments for format string";
}
String str = values[value_index];
@@ -3676,8 +3695,7 @@ String String::sprintf(const Array& values) const {
}
case 'c': {
if (value_index >= values.size()) {
- ERR_EXPLAIN("not enough arguments for format string");
- ERR_FAIL_V("");
+ return "not enough arguments for format string";
}
// Convert to character.
@@ -3685,22 +3703,18 @@ String String::sprintf(const Array& values) const {
if (values[value_index].is_num()) {
int value = values[value_index];
if (value < 0) {
- ERR_EXPLAIN("unsigned byte integer is lower than maximum")
- ERR_FAIL_V("");
+ return "unsigned byte integer is lower than maximum";
} else if (value > 255) {
- ERR_EXPLAIN("unsigned byte integer is greater than maximum")
- ERR_FAIL_V("");
+ return "unsigned byte integer is greater than maximum";
}
str = chr(values[value_index]);
} else if (values[value_index].get_type() == Variant::STRING) {
str = values[value_index];
if (str.length() != 1) {
- ERR_EXPLAIN("%c requires number or single-character string");
- ERR_FAIL_V("");
+ return "%c requires number or single-character string";
}
} else {
- ERR_EXPLAIN("%c requires number or single-character string");
- ERR_FAIL_V("");
+ return "%c requires number or single-character string";
}
// Padding.
@@ -3741,8 +3755,7 @@ String String::sprintf(const Array& values) const {
}
case '.': { // Float separtor.
if (in_decimals) {
- ERR_EXPLAIN("too many decimal points in format");
- ERR_FAIL_V("");
+ return "too many decimal points in format";
}
in_decimals = true;
min_decimals = 0; // We want to add the value manually.
@@ -3751,13 +3764,11 @@ String String::sprintf(const Array& values) const {
case '*': { // Dyanmic width, based on value.
if (value_index >= values.size()) {
- ERR_EXPLAIN("not enough arguments for format string");
- ERR_FAIL_V("");
+ return "not enough arguments for format string";
}
if (!values[value_index].is_num()) {
- ERR_EXPLAIN("* wants number");
- ERR_FAIL_V("");
+ return "* wants number";
}
int size = values[value_index];
@@ -3773,8 +3784,7 @@ String String::sprintf(const Array& values) const {
}
default: {
- ERR_EXPLAIN("unsupported format character");
- ERR_FAIL_V("");
+ return "unsupported format character";
}
}
} else { // Not in format string.
@@ -3796,14 +3806,13 @@ String String::sprintf(const Array& values) const {
}
if (in_format) {
- ERR_EXPLAIN("incomplete format");
- ERR_FAIL_V("");
+ return "incomplete format";
}
if (value_index != values.size()) {
- ERR_EXPLAIN("not all arguments converted during string formatting");
- ERR_FAIL_V("");
+ return "not all arguments converted during string formatting";
}
+ *error = false;
return formatted;
}
diff --git a/core/ustring.h b/core/ustring.h
index af5ffb7c35..f79e5ce306 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -130,7 +130,7 @@ public:
String pad_zeros(int p_digits) const;
String lpad(int min_length,const String& character=" ") const;
String rpad(int min_length,const String& character=" ") const;
- String sprintf(const Array& values) const;
+ String sprintf(const Array& values, bool* error) const;
static String num(double p_num,int p_decimals=-1);
static String num_scientific(double p_num);
static String num_real(double p_num);
@@ -149,6 +149,7 @@ public:
static double to_double(const CharType* p_str, const CharType **r_end=NULL);
static int64_t to_int(const CharType* p_str,int p_len=-1);
String capitalize() const;
+ String camelcase_to_underscore() const;
int get_slice_count(String p_splitter) const;
String get_slice(String p_splitter,int p_slice) const;
@@ -225,8 +226,6 @@ public:
String(const char *p_str);
String(const CharType *p_str,int p_clip_to_len=-1);
String(const StrRange& p_range);
-
-
};
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 50a60390e5..c6b498ff28 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -511,7 +511,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM1(ColorArray,append_array);
#define VCALL_PTR0(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
#define VCALL_PTR0R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
#define VCALL_PTR1(m_type,m_method)\
@@ -519,7 +519,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
#define VCALL_PTR1R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
#define VCALL_PTR2(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
#define VCALL_PTR2R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
#define VCALL_PTR3(m_type,m_method)\
@@ -531,7 +531,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
#define VCALL_PTR4R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3]); }
#define VCALL_PTR5(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
#define VCALL_PTR5R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
@@ -685,7 +685,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_PTR0R( InputEvent, is_pressed );
VCALL_PTR1R( InputEvent, is_action );
VCALL_PTR0R( InputEvent, is_echo );
- //VCALL_PTR2( InputEvent, set_as_action );
+ VCALL_PTR2( InputEvent, set_as_action );
struct ConstructData {
@@ -1496,7 +1496,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_pressed,varray());
ADDFUNC1(INPUT_EVENT,BOOL,InputEvent,is_action,STRING,"action",varray());
ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_echo,varray());
- //ADDFUNC2(INPUT_EVENT,NIL,InputEvent,set_as_action,STRING,"action",BOOL,"pressed",varray());
+ ADDFUNC2(INPUT_EVENT,NIL,InputEvent,set_as_action,STRING,"action",BOOL,"pressed",varray());
/* REGISTER CONSTRUCTORS */
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 21bbc8c7ee..87d9738b06 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -552,6 +552,9 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
if (p_b.type==MATRIX32) {
_RETURN( *p_a._data._matrix32 * *p_b._data._matrix32 );
};
+ if (p_b.type==VECTOR2) {
+ _RETURN( p_a._data._matrix32->xform( *(const Vector2*)p_b._data._mem) );
+ };
r_valid=false;
return;
} break;
@@ -738,18 +741,22 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
_RETURN( p_a._data._int % p_b._data._int );
} else if (p_a.type==STRING) {
- const String *str=reinterpret_cast<const String*>(p_a._data._mem);
+ const String* format=reinterpret_cast<const String*>(p_a._data._mem);
+ String result;
+ bool error;
if (p_b.type==ARRAY) {
// e.g. "frog %s %d" % ["fish", 12]
- const Array *arr=reinterpret_cast<const Array*>(p_b._data._mem);
- _RETURN(str->sprintf(*arr));
+ const Array* args=reinterpret_cast<const Array*>(p_b._data._mem);
+ result=format->sprintf(*args, &error);
} else {
// e.g. "frog %d" % 12
- Array arr;
- arr.push_back(p_b);
- _RETURN(str->sprintf(arr));
+ Array args;
+ args.push_back(p_b);
+ result=format->sprintf(args, &error);
}
+ r_valid = !error;
+ _RETURN(result);
}
r_valid=false;
diff --git a/demos/2d/area_input/box_area.png b/demos/2d/area_input/box_area.png
new file mode 100644
index 0000000000..ba7c37f7de
--- /dev/null
+++ b/demos/2d/area_input/box_area.png
Binary files differ
diff --git a/demos/2d/area_input/circle_area.png b/demos/2d/area_input/circle_area.png
new file mode 100644
index 0000000000..3cc24c8a0c
--- /dev/null
+++ b/demos/2d/area_input/circle_area.png
Binary files differ
diff --git a/demos/2d/area_input/engine.cfg b/demos/2d/area_input/engine.cfg
new file mode 100644
index 0000000000..3227e9278f
--- /dev/null
+++ b/demos/2d/area_input/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="Area 2D Input Events"
+main_scene="res://input.scn"
diff --git a/demos/2d/area_input/input.gd b/demos/2d/area_input/input.gd
new file mode 100644
index 0000000000..3f719fc853
--- /dev/null
+++ b/demos/2d/area_input/input.gd
@@ -0,0 +1,16 @@
+
+extends Area2D
+
+#virtual from CollisionObject2D (also available as signal)
+func _input_event(viewport, event, shape_idx):
+ #convert event to local coordinates
+ if (event.type==InputEvent.MOUSE_MOTION):
+ event = make_input_local( event )
+ get_node("label").set_text(str(event.pos))
+
+#virtual from CollisionObject2D (also available as signal)
+func _mouse_exit():
+ get_node("label").set_text("")
+
+
+
diff --git a/demos/2d/area_input/input.scn b/demos/2d/area_input/input.scn
new file mode 100644
index 0000000000..1a2dcbc5f4
--- /dev/null
+++ b/demos/2d/area_input/input.scn
Binary files differ
diff --git a/demos/2d/fog_of_war/.fscache b/demos/2d/fog_of_war/.fscache
new file mode 100644
index 0000000000..ba5e3995f3
--- /dev/null
+++ b/demos/2d/fog_of_war/.fscache
@@ -0,0 +1,11 @@
+::res://::1422910453
+floor.png::ImageTexture::1422910453::
+fog.gd::GDScript::1422910025::
+fog.png::ImageTexture::1422908128::
+fog.scn::PackedScene::1422909435::
+fog.xml::TileSet::1422909324::
+icon.png::ImageTexture::1422811193::
+tile_edit.scn::PackedScene::1422909313::
+troll.gd::GDScript::1422909940::
+troll.png::ImageTexture::1418669358::
+troll.scn::PackedScene::1418669358::
diff --git a/demos/2d/fog_of_war/engine.cfg b/demos/2d/fog_of_war/engine.cfg
new file mode 100644
index 0000000000..5c4307b5bc
--- /dev/null
+++ b/demos/2d/fog_of_war/engine.cfg
@@ -0,0 +1,12 @@
+[application]
+
+name="Fog of War"
+main_scene="res://fog.scn"
+icon="icon.png"
+
+[input]
+
+move_up=[key(Up)]
+move_bottom=[key(Down)]
+move_left=[key(Left)]
+move_right=[key(Right)]
diff --git a/demos/2d/fog_of_war/floor.png b/demos/2d/fog_of_war/floor.png
new file mode 100644
index 0000000000..07b4f8c98f
--- /dev/null
+++ b/demos/2d/fog_of_war/floor.png
Binary files differ
diff --git a/demos/2d/fog_of_war/fog.gd b/demos/2d/fog_of_war/fog.gd
new file mode 100644
index 0000000000..9da5680e4d
--- /dev/null
+++ b/demos/2d/fog_of_war/fog.gd
@@ -0,0 +1,86 @@
+
+extends TileMap
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+# boundarys for the fog rectangle
+var x_min = -20 # left start tile
+var x_max = 20 # right end tile
+var y_min = -20 # top start tile
+var y_max = 20 # bottom end tile
+
+var position # players position
+
+# iteration variables
+var x
+var y
+
+# variable to check if player moved
+var x_old
+var y_old
+
+# array to build up the visible area like a square
+# first value determines the width/height of the tip
+# here it would be 2*2 + 1 = 5 tiles wide/high
+# second value determines the total squares size
+# here it would be 5*2 + 1 = 10 tiles wide/high
+var l = range(2,5)
+
+# process that runs in realtime
+func _fixed_process(delta):
+ position = get_node("../troll").get_pos()
+
+ # calculate the corresponding tile
+ # from the players position
+ x = int(position.x/get_cell_size().x)
+ # switching from positive to negative tile positions
+ # causes problems because of rounding problems
+ if position.x < 0:
+ x -= 1 # correct negative values
+
+ y = int(position.y/get_cell_size().y)
+ if position.y < 0:
+ y -= 1
+
+ # check if the player moved one tile further
+ if (x_old != x) or (y_old != y):
+
+ # create the transparent part (visited area)
+ var end = l.size()-1
+ var start = 0
+ for steps in range(l.size()):
+ for m in range(x-l[end]-1,x+l[end]+2):
+ for n in range(y-l[start]-1,y+l[start]+2):
+ if get_cell(m,n) != 0:
+ set_cell(m,n,1,0,0)
+ end -= 1
+ start += 1
+
+ # create the actual and active visible part
+ var end = l.size()-1
+ var start = 0
+ for steps in range(l.size()):
+ for m in range(x-l[end],x+l[end]+1):
+ for n in range(y-l[start],y+l[start]+1):
+ set_cell(m,n,-1)
+ end -= 1
+ start += 1
+
+ x_old = x
+ y_old = y
+
+ pass
+
+func _ready():
+ # Initalization here
+
+ # create a square filled with the 100% opaque fog
+ for x in range(x_min,x_max):
+ for y in range(y_min,y_max):
+ set_cell(x,y,0,0,0)
+ set_fixed_process(true)
+ pass
+
+
diff --git a/demos/2d/fog_of_war/fog.png b/demos/2d/fog_of_war/fog.png
new file mode 100644
index 0000000000..56980c298d
--- /dev/null
+++ b/demos/2d/fog_of_war/fog.png
Binary files differ
diff --git a/demos/2d/fog_of_war/fog.scn b/demos/2d/fog_of_war/fog.scn
new file mode 100644
index 0000000000..4987f1ead5
--- /dev/null
+++ b/demos/2d/fog_of_war/fog.scn
Binary files differ
diff --git a/demos/2d/fog_of_war/fog.xml b/demos/2d/fog_of_war/fog.xml
new file mode 100644
index 0000000000..ed08d84a1f
--- /dev/null
+++ b/demos/2d/fog_of_war/fog.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<resource_file type="TileSet" subresource_count="3" version="1.0" version_name="Godot Engine v1.0.stable.custom_build">
+ <ext_resource path="res://floor.png" type="Texture"></ext_resource>
+ <ext_resource path="res://fog.png" type="Texture"></ext_resource>
+ <main_resource>
+ <string name="0/name"> "fog opaque" </string>
+ <resource name="0/texture" resource_type="Texture" path="res://fog.png"> </resource>
+ <vector2 name="0/tex_offset"> -48, -48 </vector2>
+ <vector2 name="0/shape_offset"> 0, 0 </vector2>
+ <rect2 name="0/region"> 0, 0, 144, 144 </rect2>
+ <array name="0/shapes" len="0" shared="false">
+ </array>
+ <string name="1/name"> "fog transparent" </string>
+ <resource name="1/texture" resource_type="Texture" path="res://fog.png"> </resource>
+ <vector2 name="1/tex_offset"> -48, -48 </vector2>
+ <vector2 name="1/shape_offset"> 0, 0 </vector2>
+ <rect2 name="1/region"> 144, 0, 144, 144 </rect2>
+ <array name="1/shapes" len="0" shared="false">
+ </array>
+ <string name="2/name"> "floor" </string>
+ <resource name="2/texture" resource_type="Texture" path="res://floor.png"> </resource>
+ <vector2 name="2/tex_offset"> 0, 0 </vector2>
+ <vector2 name="2/shape_offset"> 0, 0 </vector2>
+ <rect2 name="2/region"> 0, 0, 0, 0 </rect2>
+ <array name="2/shapes" len="0" shared="false">
+ </array>
+
+ </main_resource>
+</resource_file> \ No newline at end of file
diff --git a/demos/2d/fog_of_war/icon.png b/demos/2d/fog_of_war/icon.png
new file mode 100644
index 0000000000..a483390048
--- /dev/null
+++ b/demos/2d/fog_of_war/icon.png
Binary files differ
diff --git a/demos/2d/fog_of_war/icon.png.flags b/demos/2d/fog_of_war/icon.png.flags
new file mode 100644
index 0000000000..dbef2209e8
--- /dev/null
+++ b/demos/2d/fog_of_war/icon.png.flags
@@ -0,0 +1 @@
+gen_mipmaps=true
diff --git a/demos/2d/fog_of_war/tile_edit.scn b/demos/2d/fog_of_war/tile_edit.scn
new file mode 100644
index 0000000000..aaca19d370
--- /dev/null
+++ b/demos/2d/fog_of_war/tile_edit.scn
Binary files differ
diff --git a/demos/2d/fog_of_war/troll.gd b/demos/2d/fog_of_war/troll.gd
new file mode 100644
index 0000000000..d118d3a2ba
--- /dev/null
+++ b/demos/2d/fog_of_war/troll.gd
@@ -0,0 +1,43 @@
+
+extends KinematicBody2D
+
+# This is a simple collision demo showing how
+# the kinematic cotroller works.
+# move() will allow to move the node, and will
+# always move it to a non-colliding spot,
+# as long as it starts from a non-colliding spot too.
+
+
+#pixels / second
+const MOTION_SPEED=160
+
+func _fixed_process(delta):
+
+ var motion = Vector2()
+
+ if (Input.is_action_pressed("move_up")):
+ motion+=Vector2(0,-1)
+ if (Input.is_action_pressed("move_bottom")):
+ motion+=Vector2(0,1)
+ if (Input.is_action_pressed("move_left")):
+ motion+=Vector2(-1,0)
+ if (Input.is_action_pressed("move_right")):
+ motion+=Vector2(1,0)
+
+ motion = motion.normalized() * MOTION_SPEED * delta
+ motion = move(motion)
+
+ #make character slide nicely through the world
+ var slide_attempts = 4
+ while(is_colliding() and slide_attempts>0):
+ motion = get_collision_normal().slide(motion)
+ motion=move(motion)
+ slide_attempts-=1
+
+
+func _ready():
+ # Initalization here
+ set_fixed_process(true)
+ pass
+
+
diff --git a/demos/2d/fog_of_war/troll.png b/demos/2d/fog_of_war/troll.png
new file mode 100644
index 0000000000..69f195d034
--- /dev/null
+++ b/demos/2d/fog_of_war/troll.png
Binary files differ
diff --git a/demos/2d/fog_of_war/troll.scn b/demos/2d/fog_of_war/troll.scn
new file mode 100644
index 0000000000..f5d87c3631
--- /dev/null
+++ b/demos/2d/fog_of_war/troll.scn
Binary files differ
diff --git a/demos/2d/hdr/beach_cave.gd b/demos/2d/hdr/beach_cave.gd
new file mode 100644
index 0000000000..9dffbc4662
--- /dev/null
+++ b/demos/2d/hdr/beach_cave.gd
@@ -0,0 +1,26 @@
+
+extends Node2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const CAVE_LIMIT=1000
+
+func _input(ev):
+ if (ev.type==InputEvent.MOUSE_MOTION and ev.button_mask&1):
+ var rel_x = ev.relative_x
+ var cavepos = get_node("cave").get_pos()
+ cavepos.x+=rel_x
+ if (cavepos.x<-CAVE_LIMIT):
+ cavepos.x=-CAVE_LIMIT
+ elif (cavepos.x>0):
+ cavepos.x=0
+ get_node("cave").set_pos(cavepos)
+
+
+func _ready():
+ set_process_input(true)
+ # Initialization here
+ pass
+
+
diff --git a/demos/2d/hdr/beach_cave.scn b/demos/2d/hdr/beach_cave.scn
new file mode 100644
index 0000000000..4147a130ad
--- /dev/null
+++ b/demos/2d/hdr/beach_cave.scn
Binary files differ
diff --git a/demos/2d/hdr/engine.cfg b/demos/2d/hdr/engine.cfg
new file mode 100644
index 0000000000..3d8b4222d5
--- /dev/null
+++ b/demos/2d/hdr/engine.cfg
@@ -0,0 +1,13 @@
+[application]
+
+name="HDR for 2D"
+main_scene="res://beach_cave.scn"
+
+[display]
+
+width=1080
+height=720
+
+[rasterizer]
+
+blur_buffer_size=128
diff --git a/demos/2d/hdr/ocean_beach.png b/demos/2d/hdr/ocean_beach.png
new file mode 100644
index 0000000000..a873d4f61d
--- /dev/null
+++ b/demos/2d/hdr/ocean_beach.png
Binary files differ
diff --git a/demos/2d/hdr/ocean_beach.png.flags b/demos/2d/hdr/ocean_beach.png.flags
new file mode 100644
index 0000000000..82127bd7d5
--- /dev/null
+++ b/demos/2d/hdr/ocean_beach.png.flags
@@ -0,0 +1 @@
+tolinear=true
diff --git a/demos/2d/hdr/ocean_cave.png b/demos/2d/hdr/ocean_cave.png
new file mode 100644
index 0000000000..8875499df3
--- /dev/null
+++ b/demos/2d/hdr/ocean_cave.png
Binary files differ
diff --git a/demos/2d/hdr/ocean_cave.png.flags b/demos/2d/hdr/ocean_cave.png.flags
new file mode 100644
index 0000000000..82127bd7d5
--- /dev/null
+++ b/demos/2d/hdr/ocean_cave.png.flags
@@ -0,0 +1 @@
+tolinear=true
diff --git a/demos/2d/isometric/dungeon.scn b/demos/2d/isometric/dungeon.scn
index 76532a44aa..58c530d5c5 100644
--- a/demos/2d/isometric/dungeon.scn
+++ b/demos/2d/isometric/dungeon.scn
Binary files differ
diff --git a/demos/2d/isometric_light/character_shder.res b/demos/2d/isometric_light/character_shder.res
new file mode 100644
index 0000000000..ca221f766c
--- /dev/null
+++ b/demos/2d/isometric_light/character_shder.res
Binary files differ
diff --git a/demos/2d/isometric_light/column.scn b/demos/2d/isometric_light/column.scn
new file mode 100644
index 0000000000..f0b7683885
--- /dev/null
+++ b/demos/2d/isometric_light/column.scn
Binary files differ
diff --git a/demos/2d/isometric_light/cubio.gd b/demos/2d/isometric_light/cubio.gd
new file mode 100644
index 0000000000..30c766936c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio.gd
@@ -0,0 +1,96 @@
+
+extends KinematicBody2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const MAX_SPEED = 300.0
+const IDLE_SPEED = 10.0
+const ACCEL=5.0
+const VSCALE=0.5
+const SHOOT_INTERVAL=0.3
+
+var speed=Vector2()
+var current_anim=""
+var current_mirror=false
+
+var shoot_countdown=0
+
+func _input(ev):
+ if (ev.type==InputEvent.MOUSE_BUTTON and ev.button_index==1 and ev.pressed and shoot_countdown<=0):
+ var pos = get_canvas_transform().affine_inverse() * ev.pos
+ var dir = (pos-get_global_pos()).normalized()
+ var bullet = preload("res://shoot.scn").instance()
+ bullet.advance_dir=dir
+ bullet.set_pos( get_global_pos() + dir * 60 )
+ get_parent().add_child(bullet)
+ shoot_countdown=SHOOT_INTERVAL
+
+
+
+
+func _fixed_process(delta):
+
+ shoot_countdown-=delta
+ var dir = Vector2()
+ if (Input.is_action_pressed("up")):
+ dir+=Vector2(0,-1)
+ if (Input.is_action_pressed("down")):
+ dir+=Vector2(0,1)
+ if (Input.is_action_pressed("left")):
+ dir+=Vector2(-1,0)
+ if (Input.is_action_pressed("right")):
+ dir+=Vector2(1,0)
+
+ if (dir!=Vector2()):
+ dir=dir.normalized()
+ speed = speed.linear_interpolate(dir*MAX_SPEED,delta*ACCEL)
+ var motion = speed * delta
+ motion.y*=VSCALE
+ motion=move(motion)
+
+ if (is_colliding()):
+ var n = get_collision_normal()
+ motion=n.slide(motion)
+ move(motion)
+
+ var next_anim=""
+ var next_mirror=false
+
+ if (dir==Vector2() and speed.length()<IDLE_SPEED):
+ next_anim="idle"
+ next_mirror=false
+ elif (speed.length()>IDLE_SPEED*0.1):
+ var angle = atan2(abs(speed.x),speed.y)
+
+ next_mirror = speed.x>0
+ if (angle<PI/8):
+ next_anim="bottom"
+ next_mirror=false
+ elif (angle<PI/4+PI/8):
+ next_anim="bottom_left"
+ elif (angle<PI*2/4+PI/8):
+ next_anim="left"
+ elif (angle<PI*3/4+PI/8):
+ next_anim="top_left"
+ else:
+ next_anim="top"
+ next_mirror=false
+
+
+ if (next_anim!=current_anim or next_mirror!=current_mirror):
+ get_node("frames").set_flip_h(next_mirror)
+ get_node("anim").play(next_anim)
+ current_anim=next_anim
+ current_mirror=next_mirror
+
+
+
+func _ready():
+ # Initialization here
+ set_fixed_process(true)
+ set_process_input(true)
+ pass
+
+
diff --git a/demos/2d/isometric_light/cubio.scn b/demos/2d/isometric_light/cubio.scn
new file mode 100644
index 0000000000..c8ab7ddd4e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio.scn
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0001.png b/demos/2d/isometric_light/cubio/idle0001.png
new file mode 100644
index 0000000000..837dd38f9c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0001.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0002.png b/demos/2d/isometric_light/cubio/idle0002.png
new file mode 100644
index 0000000000..6137a37a9d
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0002.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0003.png b/demos/2d/isometric_light/cubio/idle0003.png
new file mode 100644
index 0000000000..7f3e3e0e31
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0003.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0004.png b/demos/2d/isometric_light/cubio/idle0004.png
new file mode 100644
index 0000000000..0a697dadf9
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0004.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0005.png b/demos/2d/isometric_light/cubio/idle0005.png
new file mode 100644
index 0000000000..9c47197247
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0005.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0006.png b/demos/2d/isometric_light/cubio/idle0006.png
new file mode 100644
index 0000000000..717a7be5b1
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0006.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0007.png b/demos/2d/isometric_light/cubio/idle0007.png
new file mode 100644
index 0000000000..dde18399f3
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0007.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0008.png b/demos/2d/isometric_light/cubio/idle0008.png
new file mode 100644
index 0000000000..0f716a5d84
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0008.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0009.png b/demos/2d/isometric_light/cubio/idle0009.png
new file mode 100644
index 0000000000..d271373f9d
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0009.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0010.png b/demos/2d/isometric_light/cubio/idle0010.png
new file mode 100644
index 0000000000..61311be0eb
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0010.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0011.png b/demos/2d/isometric_light/cubio/idle0011.png
new file mode 100644
index 0000000000..0b7d32d138
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0011.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0012.png b/demos/2d/isometric_light/cubio/idle0012.png
new file mode 100644
index 0000000000..c176034cfa
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0012.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0013.png b/demos/2d/isometric_light/cubio/idle0013.png
new file mode 100644
index 0000000000..c37018154b
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0013.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0014.png b/demos/2d/isometric_light/cubio/idle0014.png
new file mode 100644
index 0000000000..a4613e4269
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0014.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0015.png b/demos/2d/isometric_light/cubio/idle0015.png
new file mode 100644
index 0000000000..8354588b72
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0015.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0016.png b/demos/2d/isometric_light/cubio/idle0016.png
new file mode 100644
index 0000000000..4e5796fb89
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0016.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0017.png b/demos/2d/isometric_light/cubio/idle0017.png
new file mode 100644
index 0000000000..a4ac7e8c43
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0017.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0018.png b/demos/2d/isometric_light/cubio/idle0018.png
new file mode 100644
index 0000000000..aa7cc8fe6c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0018.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0019.png b/demos/2d/isometric_light/cubio/idle0019.png
new file mode 100644
index 0000000000..3ab603ceda
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0019.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0020.png b/demos/2d/isometric_light/cubio/idle0020.png
new file mode 100644
index 0000000000..9f02648f1a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0020.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0021.png b/demos/2d/isometric_light/cubio/idle0021.png
new file mode 100644
index 0000000000..ec37fc331f
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0021.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0022.png b/demos/2d/isometric_light/cubio/idle0022.png
new file mode 100644
index 0000000000..34bf331af0
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0022.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0023.png b/demos/2d/isometric_light/cubio/idle0023.png
new file mode 100644
index 0000000000..80a458146e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0023.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0024.png b/demos/2d/isometric_light/cubio/idle0024.png
new file mode 100644
index 0000000000..cd08c6d14a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0024.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0025.png b/demos/2d/isometric_light/cubio/idle0025.png
new file mode 100644
index 0000000000..de500512d4
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0025.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0026.png b/demos/2d/isometric_light/cubio/idle0026.png
new file mode 100644
index 0000000000..4a8335a248
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0026.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0027.png b/demos/2d/isometric_light/cubio/idle0027.png
new file mode 100644
index 0000000000..c3d1609a03
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0027.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0028.png b/demos/2d/isometric_light/cubio/idle0028.png
new file mode 100644
index 0000000000..96c1f32223
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0028.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0029.png b/demos/2d/isometric_light/cubio/idle0029.png
new file mode 100644
index 0000000000..5b72d02300
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0029.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0030.png b/demos/2d/isometric_light/cubio/idle0030.png
new file mode 100644
index 0000000000..a84787bf0a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0030.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0031.png b/demos/2d/isometric_light/cubio/idle0031.png
new file mode 100644
index 0000000000..dc9cd7ddc5
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0031.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0032.png b/demos/2d/isometric_light/cubio/idle0032.png
new file mode 100644
index 0000000000..c99f2e52bc
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0032.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0033.png b/demos/2d/isometric_light/cubio/idle0033.png
new file mode 100644
index 0000000000..cf5c648f9e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0033.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0034.png b/demos/2d/isometric_light/cubio/idle0034.png
new file mode 100644
index 0000000000..8e18e12d8d
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0034.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0035.png b/demos/2d/isometric_light/cubio/idle0035.png
new file mode 100644
index 0000000000..ee2c25ee96
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0035.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0036.png b/demos/2d/isometric_light/cubio/idle0036.png
new file mode 100644
index 0000000000..f452b5db33
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0036.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0037.png b/demos/2d/isometric_light/cubio/idle0037.png
new file mode 100644
index 0000000000..7768c712e3
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0037.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0038.png b/demos/2d/isometric_light/cubio/idle0038.png
new file mode 100644
index 0000000000..1200127116
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0038.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0039.png b/demos/2d/isometric_light/cubio/idle0039.png
new file mode 100644
index 0000000000..25219f0582
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0039.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0040.png b/demos/2d/isometric_light/cubio/idle0040.png
new file mode 100644
index 0000000000..8da0a81050
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0040.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0041.png b/demos/2d/isometric_light/cubio/idle0041.png
new file mode 100644
index 0000000000..fa102aec8a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0041.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0042.png b/demos/2d/isometric_light/cubio/idle0042.png
new file mode 100644
index 0000000000..0d19c32572
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0042.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0043.png b/demos/2d/isometric_light/cubio/idle0043.png
new file mode 100644
index 0000000000..bf284c62d0
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0043.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0044.png b/demos/2d/isometric_light/cubio/idle0044.png
new file mode 100644
index 0000000000..3daa1be0b8
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0044.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0045.png b/demos/2d/isometric_light/cubio/idle0045.png
new file mode 100644
index 0000000000..92abe74295
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0045.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0046.png b/demos/2d/isometric_light/cubio/idle0046.png
new file mode 100644
index 0000000000..2a1ab0f036
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0046.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0047.png b/demos/2d/isometric_light/cubio/idle0047.png
new file mode 100644
index 0000000000..da38b835ef
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0047.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0048.png b/demos/2d/isometric_light/cubio/idle0048.png
new file mode 100644
index 0000000000..35fac1b602
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0048.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0049.png b/demos/2d/isometric_light/cubio/idle0049.png
new file mode 100644
index 0000000000..7ebd79b8d7
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0049.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0050.png b/demos/2d/isometric_light/cubio/idle0050.png
new file mode 100644
index 0000000000..ba0678ba87
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0050.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0051.png b/demos/2d/isometric_light/cubio/idle0051.png
new file mode 100644
index 0000000000..03c54f1232
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0051.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0052.png b/demos/2d/isometric_light/cubio/idle0052.png
new file mode 100644
index 0000000000..0e2c8b5d9f
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0052.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0053.png b/demos/2d/isometric_light/cubio/idle0053.png
new file mode 100644
index 0000000000..d95095937f
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0053.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0054.png b/demos/2d/isometric_light/cubio/idle0054.png
new file mode 100644
index 0000000000..5a09fce69e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0054.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0055.png b/demos/2d/isometric_light/cubio/idle0055.png
new file mode 100644
index 0000000000..6e2aad9d70
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0055.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0056.png b/demos/2d/isometric_light/cubio/idle0056.png
new file mode 100644
index 0000000000..45813e953f
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0056.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0057.png b/demos/2d/isometric_light/cubio/idle0057.png
new file mode 100644
index 0000000000..579b4e1647
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0057.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0058.png b/demos/2d/isometric_light/cubio/idle0058.png
new file mode 100644
index 0000000000..236f290651
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0058.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0059.png b/demos/2d/isometric_light/cubio/idle0059.png
new file mode 100644
index 0000000000..837dd38f9c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0059.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/idle0060.png b/demos/2d/isometric_light/cubio/idle0060.png
new file mode 100644
index 0000000000..837dd38f9c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/idle0060.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0001.png b/demos/2d/isometric_light/cubio/norm-b-0001.png
new file mode 100644
index 0000000000..cda17e21cc
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0001.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0002.png b/demos/2d/isometric_light/cubio/norm-b-0002.png
new file mode 100644
index 0000000000..fb36728cdf
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0002.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0003.png b/demos/2d/isometric_light/cubio/norm-b-0003.png
new file mode 100644
index 0000000000..c8bfecb100
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0003.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0004.png b/demos/2d/isometric_light/cubio/norm-b-0004.png
new file mode 100644
index 0000000000..e91213434f
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0004.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0005.png b/demos/2d/isometric_light/cubio/norm-b-0005.png
new file mode 100644
index 0000000000..a823fe9a92
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0005.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0006.png b/demos/2d/isometric_light/cubio/norm-b-0006.png
new file mode 100644
index 0000000000..d9de12baad
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0006.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0007.png b/demos/2d/isometric_light/cubio/norm-b-0007.png
new file mode 100644
index 0000000000..f042eed408
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0007.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0008.png b/demos/2d/isometric_light/cubio/norm-b-0008.png
new file mode 100644
index 0000000000..e18ca607dd
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0008.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0009.png b/demos/2d/isometric_light/cubio/norm-b-0009.png
new file mode 100644
index 0000000000..7e7ddd4c63
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0009.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0010.png b/demos/2d/isometric_light/cubio/norm-b-0010.png
new file mode 100644
index 0000000000..fddb956099
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0010.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0011.png b/demos/2d/isometric_light/cubio/norm-b-0011.png
new file mode 100644
index 0000000000..240a50a9ec
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0011.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0012.png b/demos/2d/isometric_light/cubio/norm-b-0012.png
new file mode 100644
index 0000000000..3e38628e98
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0012.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0013.png b/demos/2d/isometric_light/cubio/norm-b-0013.png
new file mode 100644
index 0000000000..2380e76909
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0013.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0014.png b/demos/2d/isometric_light/cubio/norm-b-0014.png
new file mode 100644
index 0000000000..db374927c6
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0014.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0015.png b/demos/2d/isometric_light/cubio/norm-b-0015.png
new file mode 100644
index 0000000000..1cd0e762c5
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0015.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0016.png b/demos/2d/isometric_light/cubio/norm-b-0016.png
new file mode 100644
index 0000000000..0d894db3f4
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0016.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0017.png b/demos/2d/isometric_light/cubio/norm-b-0017.png
new file mode 100644
index 0000000000..c184af8e85
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0017.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0018.png b/demos/2d/isometric_light/cubio/norm-b-0018.png
new file mode 100644
index 0000000000..1db06014b7
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0018.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0019.png b/demos/2d/isometric_light/cubio/norm-b-0019.png
new file mode 100644
index 0000000000..e74c9c7954
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0019.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-b-0020.png b/demos/2d/isometric_light/cubio/norm-b-0020.png
new file mode 100644
index 0000000000..326e60c64a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-b-0020.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0001.png b/demos/2d/isometric_light/cubio/norm-bl-0001.png
new file mode 100644
index 0000000000..0b36e8caa3
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0001.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0002.png b/demos/2d/isometric_light/cubio/norm-bl-0002.png
new file mode 100644
index 0000000000..f00166d140
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0002.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0003.png b/demos/2d/isometric_light/cubio/norm-bl-0003.png
new file mode 100644
index 0000000000..d84993e097
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0003.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0004.png b/demos/2d/isometric_light/cubio/norm-bl-0004.png
new file mode 100644
index 0000000000..8e4c7f278b
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0004.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0005.png b/demos/2d/isometric_light/cubio/norm-bl-0005.png
new file mode 100644
index 0000000000..5009f2a514
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0005.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0006.png b/demos/2d/isometric_light/cubio/norm-bl-0006.png
new file mode 100644
index 0000000000..d0d654de6e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0006.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0007.png b/demos/2d/isometric_light/cubio/norm-bl-0007.png
new file mode 100644
index 0000000000..2df2437a0d
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0007.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0008.png b/demos/2d/isometric_light/cubio/norm-bl-0008.png
new file mode 100644
index 0000000000..4bb8e91ecc
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0008.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0009.png b/demos/2d/isometric_light/cubio/norm-bl-0009.png
new file mode 100644
index 0000000000..e4ab80ab72
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0009.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0010.png b/demos/2d/isometric_light/cubio/norm-bl-0010.png
new file mode 100644
index 0000000000..7ead89343f
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0010.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0011.png b/demos/2d/isometric_light/cubio/norm-bl-0011.png
new file mode 100644
index 0000000000..9714999645
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0011.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0012.png b/demos/2d/isometric_light/cubio/norm-bl-0012.png
new file mode 100644
index 0000000000..95e0117df8
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0012.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0013.png b/demos/2d/isometric_light/cubio/norm-bl-0013.png
new file mode 100644
index 0000000000..85d4f25e7e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0013.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0014.png b/demos/2d/isometric_light/cubio/norm-bl-0014.png
new file mode 100644
index 0000000000..3c9cc526d0
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0014.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0015.png b/demos/2d/isometric_light/cubio/norm-bl-0015.png
new file mode 100644
index 0000000000..3e30649ce1
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0015.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0016.png b/demos/2d/isometric_light/cubio/norm-bl-0016.png
new file mode 100644
index 0000000000..f39399c369
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0016.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0017.png b/demos/2d/isometric_light/cubio/norm-bl-0017.png
new file mode 100644
index 0000000000..47f79741a1
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0017.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0018.png b/demos/2d/isometric_light/cubio/norm-bl-0018.png
new file mode 100644
index 0000000000..8f4ccdcf33
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0018.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0019.png b/demos/2d/isometric_light/cubio/norm-bl-0019.png
new file mode 100644
index 0000000000..a278ec0f05
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0019.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-bl-0020.png b/demos/2d/isometric_light/cubio/norm-bl-0020.png
new file mode 100644
index 0000000000..db5fd0b73c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-bl-0020.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0001.png b/demos/2d/isometric_light/cubio/norm-l-0001.png
new file mode 100644
index 0000000000..7a989e79dd
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0001.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0002.png b/demos/2d/isometric_light/cubio/norm-l-0002.png
new file mode 100644
index 0000000000..2257923ee6
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0002.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0003.png b/demos/2d/isometric_light/cubio/norm-l-0003.png
new file mode 100644
index 0000000000..2e264e49a4
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0003.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0004.png b/demos/2d/isometric_light/cubio/norm-l-0004.png
new file mode 100644
index 0000000000..e0061451d6
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0004.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0005.png b/demos/2d/isometric_light/cubio/norm-l-0005.png
new file mode 100644
index 0000000000..e16cca081c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0005.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0006.png b/demos/2d/isometric_light/cubio/norm-l-0006.png
new file mode 100644
index 0000000000..694c2163eb
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0006.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0007.png b/demos/2d/isometric_light/cubio/norm-l-0007.png
new file mode 100644
index 0000000000..ed2ae64cad
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0007.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0008.png b/demos/2d/isometric_light/cubio/norm-l-0008.png
new file mode 100644
index 0000000000..4bbaeb8006
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0008.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0009.png b/demos/2d/isometric_light/cubio/norm-l-0009.png
new file mode 100644
index 0000000000..1f53a1067b
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0009.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0010.png b/demos/2d/isometric_light/cubio/norm-l-0010.png
new file mode 100644
index 0000000000..2007942a2a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0010.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0011.png b/demos/2d/isometric_light/cubio/norm-l-0011.png
new file mode 100644
index 0000000000..0c27288646
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0011.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0012.png b/demos/2d/isometric_light/cubio/norm-l-0012.png
new file mode 100644
index 0000000000..8b885bcee8
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0012.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0013.png b/demos/2d/isometric_light/cubio/norm-l-0013.png
new file mode 100644
index 0000000000..ed08c9a470
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0013.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0014.png b/demos/2d/isometric_light/cubio/norm-l-0014.png
new file mode 100644
index 0000000000..3b6088c9a0
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0014.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0015.png b/demos/2d/isometric_light/cubio/norm-l-0015.png
new file mode 100644
index 0000000000..1ffa2b8cda
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0015.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0016.png b/demos/2d/isometric_light/cubio/norm-l-0016.png
new file mode 100644
index 0000000000..00279dc052
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0016.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0017.png b/demos/2d/isometric_light/cubio/norm-l-0017.png
new file mode 100644
index 0000000000..1805000a78
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0017.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0018.png b/demos/2d/isometric_light/cubio/norm-l-0018.png
new file mode 100644
index 0000000000..1ff123533f
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0018.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0019.png b/demos/2d/isometric_light/cubio/norm-l-0019.png
new file mode 100644
index 0000000000..2faf043a2b
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0019.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-l-0020.png b/demos/2d/isometric_light/cubio/norm-l-0020.png
new file mode 100644
index 0000000000..7948d2d79d
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-l-0020.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0001.png b/demos/2d/isometric_light/cubio/norm-u-0001.png
new file mode 100644
index 0000000000..6c702ba7c3
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0001.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0002.png b/demos/2d/isometric_light/cubio/norm-u-0002.png
new file mode 100644
index 0000000000..9a151e049b
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0002.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0003.png b/demos/2d/isometric_light/cubio/norm-u-0003.png
new file mode 100644
index 0000000000..0b7464260a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0003.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0004.png b/demos/2d/isometric_light/cubio/norm-u-0004.png
new file mode 100644
index 0000000000..89061fdbcf
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0004.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0005.png b/demos/2d/isometric_light/cubio/norm-u-0005.png
new file mode 100644
index 0000000000..efc8ab0157
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0005.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0006.png b/demos/2d/isometric_light/cubio/norm-u-0006.png
new file mode 100644
index 0000000000..a89ef58f46
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0006.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0007.png b/demos/2d/isometric_light/cubio/norm-u-0007.png
new file mode 100644
index 0000000000..b069591200
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0007.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0008.png b/demos/2d/isometric_light/cubio/norm-u-0008.png
new file mode 100644
index 0000000000..8f0dbe8016
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0008.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0009.png b/demos/2d/isometric_light/cubio/norm-u-0009.png
new file mode 100644
index 0000000000..d4698f2584
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0009.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0010.png b/demos/2d/isometric_light/cubio/norm-u-0010.png
new file mode 100644
index 0000000000..cc3d442d4a
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0010.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0011.png b/demos/2d/isometric_light/cubio/norm-u-0011.png
new file mode 100644
index 0000000000..43c505d7e4
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0011.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0012.png b/demos/2d/isometric_light/cubio/norm-u-0012.png
new file mode 100644
index 0000000000..d4f955fd0c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0012.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0013.png b/demos/2d/isometric_light/cubio/norm-u-0013.png
new file mode 100644
index 0000000000..08dd875a54
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0013.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0014.png b/demos/2d/isometric_light/cubio/norm-u-0014.png
new file mode 100644
index 0000000000..4bea108a46
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0014.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0015.png b/demos/2d/isometric_light/cubio/norm-u-0015.png
new file mode 100644
index 0000000000..943c556706
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0015.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0016.png b/demos/2d/isometric_light/cubio/norm-u-0016.png
new file mode 100644
index 0000000000..d71a69c5a6
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0016.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0017.png b/demos/2d/isometric_light/cubio/norm-u-0017.png
new file mode 100644
index 0000000000..2d74e4472c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0017.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0018.png b/demos/2d/isometric_light/cubio/norm-u-0018.png
new file mode 100644
index 0000000000..17a5b10acb
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0018.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0019.png b/demos/2d/isometric_light/cubio/norm-u-0019.png
new file mode 100644
index 0000000000..e376c843e1
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0019.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-u-0020.png b/demos/2d/isometric_light/cubio/norm-u-0020.png
new file mode 100644
index 0000000000..fa1d3521ca
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-u-0020.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0001.png b/demos/2d/isometric_light/cubio/norm-ul-0001.png
new file mode 100644
index 0000000000..3e75621260
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0001.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0002.png b/demos/2d/isometric_light/cubio/norm-ul-0002.png
new file mode 100644
index 0000000000..d48d902936
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0002.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0003.png b/demos/2d/isometric_light/cubio/norm-ul-0003.png
new file mode 100644
index 0000000000..703cef6715
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0003.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0004.png b/demos/2d/isometric_light/cubio/norm-ul-0004.png
new file mode 100644
index 0000000000..7dd3e2884e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0004.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0005.png b/demos/2d/isometric_light/cubio/norm-ul-0005.png
new file mode 100644
index 0000000000..1281b9ceb8
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0005.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0006.png b/demos/2d/isometric_light/cubio/norm-ul-0006.png
new file mode 100644
index 0000000000..e3c58752e9
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0006.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0007.png b/demos/2d/isometric_light/cubio/norm-ul-0007.png
new file mode 100644
index 0000000000..ccec10c83c
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0007.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0008.png b/demos/2d/isometric_light/cubio/norm-ul-0008.png
new file mode 100644
index 0000000000..1243c7dfe8
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0008.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0009.png b/demos/2d/isometric_light/cubio/norm-ul-0009.png
new file mode 100644
index 0000000000..77ea3ca8e9
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0009.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0010.png b/demos/2d/isometric_light/cubio/norm-ul-0010.png
new file mode 100644
index 0000000000..cf1cb7d0e3
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0010.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0011.png b/demos/2d/isometric_light/cubio/norm-ul-0011.png
new file mode 100644
index 0000000000..1063ee29a8
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0011.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0012.png b/demos/2d/isometric_light/cubio/norm-ul-0012.png
new file mode 100644
index 0000000000..a896237161
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0012.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0013.png b/demos/2d/isometric_light/cubio/norm-ul-0013.png
new file mode 100644
index 0000000000..cc289b18a0
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0013.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0014.png b/demos/2d/isometric_light/cubio/norm-ul-0014.png
new file mode 100644
index 0000000000..faf36e82b6
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0014.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0015.png b/demos/2d/isometric_light/cubio/norm-ul-0015.png
new file mode 100644
index 0000000000..925be82a2e
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0015.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0016.png b/demos/2d/isometric_light/cubio/norm-ul-0016.png
new file mode 100644
index 0000000000..1cb2300b9d
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0016.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0017.png b/demos/2d/isometric_light/cubio/norm-ul-0017.png
new file mode 100644
index 0000000000..5a841b57af
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0017.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0018.png b/demos/2d/isometric_light/cubio/norm-ul-0018.png
new file mode 100644
index 0000000000..2b30df8988
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0018.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0019.png b/demos/2d/isometric_light/cubio/norm-ul-0019.png
new file mode 100644
index 0000000000..12c0a72d6d
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0019.png
Binary files differ
diff --git a/demos/2d/isometric_light/cubio/norm-ul-0020.png b/demos/2d/isometric_light/cubio/norm-ul-0020.png
new file mode 100644
index 0000000000..3cffda17ca
--- /dev/null
+++ b/demos/2d/isometric_light/cubio/norm-ul-0020.png
Binary files differ
diff --git a/demos/2d/isometric_light/energy.png b/demos/2d/isometric_light/energy.png
new file mode 100644
index 0000000000..237e3ea4f0
--- /dev/null
+++ b/demos/2d/isometric_light/energy.png
Binary files differ
diff --git a/demos/2d/isometric_light/engine.cfg b/demos/2d/isometric_light/engine.cfg
new file mode 100644
index 0000000000..0d9e432d5d
--- /dev/null
+++ b/demos/2d/isometric_light/engine.cfg
@@ -0,0 +1,18 @@
+[application]
+
+main_scene="res://map.scn"
+
+[input]
+
+up=[key(Up), key(W)]
+down=[key(S), key(Down)]
+left=[key(Left), key(A)]
+right=[key(Right), key(D)]
+
+[rasterizer]
+
+shadow_filter=0
+
+[render]
+
+default_clear_color=#ff000000
diff --git a/demos/2d/isometric_light/export.cfg b/demos/2d/isometric_light/export.cfg
new file mode 100644
index 0000000000..578d4171b2
--- /dev/null
+++ b/demos/2d/isometric_light/export.cfg
@@ -0,0 +1,262 @@
+[convert_images]
+
+action="none"
+compress_quality=0.7
+formats="png"
+shrink=1
+
+[export_filter]
+
+filter=""
+type="resources"
+
+[image_group_files]
+
+files=["res://faceNormal.png", "normal", "res://faceColor.png", "normal", "res://faceMask.png", "normal"]
+
+[image_groups]
+
+normal={"atlas":false, "action":"compress_ram", "shrink":1, "lossy_quality":0.7}
+
+[platform:Android]
+
+apk_expansion/SALT=""
+apk_expansion/enable=false
+apk_expansion/public_key=""
+command_line/extra_args=""
+custom_package/debug=""
+custom_package/release=""
+keystore/release=""
+keystore/release_password=""
+keystore/release_user=""
+one_click_deploy/clear_previous_install=true
+package/icon=""
+package/name=""
+package/signed=true
+package/unique_name="com.android.noname"
+permissions/access_checkin_properties=false
+permissions/access_coarse_location=false
+permissions/access_fine_location=false
+permissions/access_location_extra_commands=false
+permissions/access_mock_location=false
+permissions/access_network_state=false
+permissions/access_surface_flinger=false
+permissions/access_wifi_state=false
+permissions/account_manager=false
+permissions/add_voicemail=false
+permissions/authenticate_accounts=false
+permissions/battery_stats=false
+permissions/bind_accessibility_service=false
+permissions/bind_appwidget=false
+permissions/bind_device_admin=false
+permissions/bind_input_method=false
+permissions/bind_nfc_service=false
+permissions/bind_notification_listener_service=false
+permissions/bind_print_service=false
+permissions/bind_remoteviews=false
+permissions/bind_text_service=false
+permissions/bind_vpn_service=false
+permissions/bind_wallpaper=false
+permissions/bluetooth=false
+permissions/bluetooth_admin=false
+permissions/bluetooth_privileged=false
+permissions/brick=false
+permissions/broadcast_package_removed=false
+permissions/broadcast_sms=false
+permissions/broadcast_sticky=false
+permissions/broadcast_wap_push=false
+permissions/call_phone=false
+permissions/call_privileged=false
+permissions/camera=false
+permissions/capture_audio_output=false
+permissions/capture_secure_video_output=false
+permissions/capture_video_output=false
+permissions/change_component_enabled_state=false
+permissions/change_configuration=false
+permissions/change_network_state=false
+permissions/change_wifi_multicast_state=false
+permissions/change_wifi_state=false
+permissions/clear_app_cache=false
+permissions/clear_app_user_data=false
+permissions/control_location_updates=false
+permissions/delete_cache_files=false
+permissions/delete_packages=false
+permissions/device_power=false
+permissions/diagnostic=false
+permissions/disable_keyguard=false
+permissions/dump=false
+permissions/expand_status_bar=false
+permissions/factory_test=false
+permissions/flashlight=false
+permissions/force_back=false
+permissions/get_accounts=false
+permissions/get_package_size=false
+permissions/get_tasks=false
+permissions/get_top_activity_info=false
+permissions/global_search=false
+permissions/hardware_test=false
+permissions/inject_events=false
+permissions/install_location_provider=false
+permissions/install_packages=false
+permissions/install_shortcut=false
+permissions/internal_system_window=false
+permissions/internet=false
+permissions/kill_background_processes=false
+permissions/location_hardware=false
+permissions/manage_accounts=false
+permissions/manage_app_tokens=false
+permissions/manage_documents=false
+permissions/master_clear=false
+permissions/media_content_control=false
+permissions/modify_audio_settings=false
+permissions/modify_phone_state=false
+permissions/mount_format_filesystems=false
+permissions/mount_unmount_filesystems=false
+permissions/nfc=false
+permissions/persistent_activity=false
+permissions/process_outgoing_calls=false
+permissions/read_calendar=false
+permissions/read_call_log=false
+permissions/read_contacts=false
+permissions/read_external_storage=false
+permissions/read_frame_buffer=false
+permissions/read_history_bookmarks=false
+permissions/read_input_state=false
+permissions/read_logs=false
+permissions/read_phone_state=false
+permissions/read_profile=false
+permissions/read_sms=false
+permissions/read_social_stream=false
+permissions/read_sync_settings=false
+permissions/read_sync_stats=false
+permissions/read_user_dictionary=false
+permissions/reboot=false
+permissions/receive_boot_completed=false
+permissions/receive_mms=false
+permissions/receive_sms=false
+permissions/receive_wap_push=false
+permissions/record_audio=false
+permissions/reorder_tasks=false
+permissions/restart_packages=false
+permissions/send_respond_via_message=false
+permissions/send_sms=false
+permissions/set_activity_watcher=false
+permissions/set_alarm=false
+permissions/set_always_finish=false
+permissions/set_animation_scale=false
+permissions/set_debug_app=false
+permissions/set_orientation=false
+permissions/set_pointer_speed=false
+permissions/set_preferred_applications=false
+permissions/set_process_limit=false
+permissions/set_time=false
+permissions/set_time_zone=false
+permissions/set_wallpaper=false
+permissions/set_wallpaper_hints=false
+permissions/signal_persistent_processes=false
+permissions/status_bar=false
+permissions/subscribed_feeds_read=false
+permissions/subscribed_feeds_write=false
+permissions/system_alert_window=false
+permissions/transmit_ir=false
+permissions/uninstall_shortcut=false
+permissions/update_device_stats=false
+permissions/use_credentials=false
+permissions/use_sip=false
+permissions/vibrate=false
+permissions/wake_lock=false
+permissions/write_apn_settings=false
+permissions/write_calendar=false
+permissions/write_call_log=false
+permissions/write_contacts=false
+permissions/write_external_storage=false
+permissions/write_gservices=false
+permissions/write_history_bookmarks=false
+permissions/write_profile=false
+permissions/write_secure_settings=false
+permissions/write_settings=false
+permissions/write_sms=false
+permissions/write_social_stream=false
+permissions/write_sync_settings=false
+permissions/write_user_dictionary=false
+screen/orientation=0
+screen/support_large=true
+screen/support_normal=true
+screen/support_small=true
+screen/support_xlarge=true
+user_permissions/0=""
+user_permissions/1=""
+user_permissions/10=""
+user_permissions/11=""
+user_permissions/12=""
+user_permissions/13=""
+user_permissions/14=""
+user_permissions/15=""
+user_permissions/16=""
+user_permissions/17=""
+user_permissions/18=""
+user_permissions/19=""
+user_permissions/2=""
+user_permissions/3=""
+user_permissions/4=""
+user_permissions/5=""
+user_permissions/6=""
+user_permissions/7=""
+user_permissions/8=""
+user_permissions/9=""
+version/code=1
+version/name="1.0"
+
+[platform:BlackBerry 10]
+
+package/category="core.games"
+package/custom_template=""
+package/description="Game made with Godot Engine"
+package/icon=""
+package/name=""
+package/unique_name="com.godot.noname"
+release/author="Cert. Name"
+release/author_id="Cert. ID"
+version/code=1
+version/name="1.0"
+
+[platform:HTML5]
+
+browser/enable_run=false
+custom_package/debug=""
+custom_package/release=""
+options/memory_size=3
+
+[platform:Linux X11]
+
+binary/64_bits=true
+custom_binary/debug=""
+custom_binary/release=""
+resources/pack_mode=1
+
+[platform:Mac OSX]
+
+application/64_bits=false
+application/copyright=""
+application/icon=""
+application/identifier="com.godot.macgame"
+application/info="This Game is Nice"
+application/name=""
+application/short_version="1.0"
+application/signature="godotmacgame"
+application/version="1.0"
+custom_package/debug=""
+custom_package/release=""
+display/high_res=false
+
+[platform:Windows Desktop]
+
+binary/64_bits=true
+custom_binary/debug=""
+custom_binary/release=""
+resources/pack_mode=1
+
+[script]
+
+action="compile"
+encrypt_key=""
diff --git a/demos/2d/isometric_light/faceColor.png b/demos/2d/isometric_light/faceColor.png
new file mode 100644
index 0000000000..c6daf73cb7
--- /dev/null
+++ b/demos/2d/isometric_light/faceColor.png
Binary files differ
diff --git a/demos/2d/isometric_light/faceMask.png b/demos/2d/isometric_light/faceMask.png
new file mode 100644
index 0000000000..d91e968c8e
--- /dev/null
+++ b/demos/2d/isometric_light/faceMask.png
Binary files differ
diff --git a/demos/2d/isometric_light/faceNormal.png b/demos/2d/isometric_light/faceNormal.png
new file mode 100644
index 0000000000..651f075fa1
--- /dev/null
+++ b/demos/2d/isometric_light/faceNormal.png
Binary files differ
diff --git a/demos/2d/isometric_light/fire.png b/demos/2d/isometric_light/fire.png
new file mode 100644
index 0000000000..746e4f9f4b
--- /dev/null
+++ b/demos/2d/isometric_light/fire.png
Binary files differ
diff --git a/demos/2d/isometric_light/floor_shader.res b/demos/2d/isometric_light/floor_shader.res
new file mode 100644
index 0000000000..446c71d227
--- /dev/null
+++ b/demos/2d/isometric_light/floor_shader.res
Binary files differ
diff --git a/demos/2d/isometric_light/light2.png b/demos/2d/isometric_light/light2.png
new file mode 100644
index 0000000000..cd473251aa
--- /dev/null
+++ b/demos/2d/isometric_light/light2.png
Binary files differ
diff --git a/demos/2d/isometric_light/map.gd b/demos/2d/isometric_light/map.gd
new file mode 100644
index 0000000000..f712aeeaec
--- /dev/null
+++ b/demos/2d/isometric_light/map.gd
@@ -0,0 +1,18 @@
+
+extends Node2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+func _ready():
+ # Initialization here
+ pass
+
+
+
+
+func _on_prince_area_body_enter( body ):
+ if (body.get_name()=="cubio"):
+ get_node("message").show()
+ pass # replace with function body
diff --git a/demos/2d/isometric_light/map.scn b/demos/2d/isometric_light/map.scn
new file mode 100644
index 0000000000..c939a4b392
--- /dev/null
+++ b/demos/2d/isometric_light/map.scn
Binary files differ
diff --git a/demos/2d/isometric_light/shadow_blob.png b/demos/2d/isometric_light/shadow_blob.png
new file mode 100644
index 0000000000..e97fd2a826
--- /dev/null
+++ b/demos/2d/isometric_light/shadow_blob.png
Binary files differ
diff --git a/demos/2d/isometric_light/shoot.gd b/demos/2d/isometric_light/shoot.gd
new file mode 100644
index 0000000000..0486bbb658
--- /dev/null
+++ b/demos/2d/isometric_light/shoot.gd
@@ -0,0 +1,27 @@
+
+extends KinematicBody2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+var advance_dir=Vector2(1,0)
+const ADVANCE_SPEED = 500.0
+
+var hit=false
+
+func _fixed_process(delta):
+
+ if (hit):
+ return
+ move(advance_dir*delta*ADVANCE_SPEED)
+ if (is_colliding()):
+ get_node("anim").play("explode")
+ hit=true
+
+func _ready():
+ # Initialization here
+ set_fixed_process(true)
+ pass
+
+
diff --git a/demos/2d/isometric_light/shoot.scn b/demos/2d/isometric_light/shoot.scn
new file mode 100644
index 0000000000..672608810f
--- /dev/null
+++ b/demos/2d/isometric_light/shoot.scn
Binary files differ
diff --git a/demos/2d/isometric_light/shoot_halo.png b/demos/2d/isometric_light/shoot_halo.png
new file mode 100644
index 0000000000..5ba954b32b
--- /dev/null
+++ b/demos/2d/isometric_light/shoot_halo.png
Binary files differ
diff --git a/demos/2d/isometric_light/tileset.res b/demos/2d/isometric_light/tileset.res
new file mode 100644
index 0000000000..633bdada38
--- /dev/null
+++ b/demos/2d/isometric_light/tileset.res
Binary files differ
diff --git a/demos/2d/isometric_light/tileset_scene.scn b/demos/2d/isometric_light/tileset_scene.scn
new file mode 100644
index 0000000000..3d0773c9c5
--- /dev/null
+++ b/demos/2d/isometric_light/tileset_scene.scn
Binary files differ
diff --git a/demos/2d/isometric_light/torch.scn b/demos/2d/isometric_light/torch.scn
new file mode 100644
index 0000000000..d1cb7fe7e6
--- /dev/null
+++ b/demos/2d/isometric_light/torch.scn
Binary files differ
diff --git a/demos/2d/isometric_light/torch_light.png b/demos/2d/isometric_light/torch_light.png
new file mode 100644
index 0000000000..a98113d36f
--- /dev/null
+++ b/demos/2d/isometric_light/torch_light.png
Binary files differ
diff --git a/demos/2d/isometric_light/torch_shader.res b/demos/2d/isometric_light/torch_shader.res
new file mode 100644
index 0000000000..ad70d5260d
--- /dev/null
+++ b/demos/2d/isometric_light/torch_shader.res
Binary files differ
diff --git a/demos/2d/isometric_light/wall_shader.res b/demos/2d/isometric_light/wall_shader.res
new file mode 100644
index 0000000000..78c8fe57e1
--- /dev/null
+++ b/demos/2d/isometric_light/wall_shader.res
Binary files differ
diff --git a/demos/2d/platformer/stage.xml b/demos/2d/platformer/stage.xml
index 35517f747d..610057183b 100644
--- a/demos/2d/platformer/stage.xml
+++ b/demos/2d/platformer/stage.xml
@@ -2,16 +2,16 @@
<resource_file type="PackedScene" subresource_count="9" version="1.0" version_name="Godot Engine v1.0.stable.custom_build">
<ext_resource path="res://music.ogg" type="AudioStream"></ext_resource>
<ext_resource path="res://tileset.xml" type="TileSet"></ext_resource>
- <ext_resource path="res://coin.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource>
+ <ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource>
+ <ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource>
+ <ext_resource path="res://coin.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://enemy.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource>
<main_resource>
<dictionary name="_bundled" shared="false">
<string> "names" </string>
- <string_array len="127">
+ <string_array len="130">
<string> "stage" </string>
<string> "Node" </string>
<string> "_import_path" </string>
@@ -21,6 +21,7 @@
<string> "visibility/visible" </string>
<string> "visibility/opacity" </string>
<string> "visibility/self_opacity" </string>
+ <string> "visibility/light_mask" </string>
<string> "transform/pos" </string>
<string> "transform/rot" </string>
<string> "transform/scale" </string>
@@ -32,7 +33,9 @@
<string> "cell/quadrant_size" </string>
<string> "cell/custom_transform" </string>
<string> "cell/half_offset" </string>
- <string> "collision/body_mode" </string>
+ <string> "cell/tile_origin" </string>
+ <string> "cell/y_sort" </string>
+ <string> "collision/use_kinematic" </string>
<string> "collision/friction" </string>
<string> "collision/bounce" </string>
<string> "collision/layers" </string>
@@ -172,10 +175,10 @@
<real> 0.814506 </real>
<string> "use_snap" </string>
<bool> False </bool>
+ <string> "snap_vec" </string>
+ <vector2> 10, 10 </vector2>
<string> "ofs" </string>
- <vector2> -121.031, 464.121 </vector2>
- <string> "snap" </string>
- <int> 10 </int>
+ <vector2> 177.488, 709.633 </vector2>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
@@ -278,10 +281,11 @@
<int> 0 </int>
</dictionary>
<string> "__editor_plugin_screen__" </string>
- <string> "2D" </string>
+ <string> "3D" </string>
</dictionary>
<bool> True </bool>
<real> 1 </real>
+ <int> 1 </int>
<vector2> 0, 0 </vector2>
<real> 0 </real>
<vector2> 1, 1 </vector2>
@@ -291,7 +295,7 @@
<int> 8 </int>
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
<int> 2 </int>
- <int> 1 </int>
+ <bool> False </bool>
<int_array len="1998"> 0, 2, 70, 536870914, 71, 10, 72, 10, 73, 10, 74, 10, 75, 10, 76, 10, 77, 10, 78, 10, 65536, 2, 65606, 536870914, 65607, 10, 65608, 10, 65609, 10, 65610, 10, 65611, 10, 65612, 10, 65613, 10, 65614, 10, 131072, 2, 131142, 536870914, 131143, 10, 131144, 10, 131145, 10, 131146, 10, 131147, 10, 131148, 10, 131149, 10, 131150, 10, 196608, 2, 196626, 9, 196678, 536870914, 196679, 10, 196680, 10, 196681, 10, 196682, 10, 196683, 10, 196684, 10, 196685, 10, 196686, 10, 262144, 2, 262162, 8, 262214, 536870914, 262215, 10, 262216, 10, 262217, 10, 262218, 10, 262219, 10, 262220, 10, 262221, 10, 262222, 10, 327680, 2, 327697, 536870921, 327698, 7, 327733, 9, 327750, 536870914, 327751, 10, 327752, 10, 327753, 10, 327754, 10, 327755, 10, 327756, 10, 327757, 10, 327758, 10, 393216, 2, 393233, 536870920, 393234, 7, 393257, 9, 393269, 7, 393286, 536870914, 393287, 10, 393288, 10, 393289, 10, 393290, 10, 393291, 10, 393292, 10, 393293, 10, 393294, 10, 458752, 2, 458769, 7, 458770, 8, 458790, 9, 458793, 8, 458805, 8, 458822, 536870914, 458823, 10, 458824, 10, 458825, 10, 458826, 10, 458827, 10, 458828, 10, 458829, 10, 458830, 10, 524288, 4, 524289, 1, 524304, 536870913, 524305, 536870918, 524306, 6, 524307, 5, 524308, 1, 524326, 8, 524329, 7, 524341, 7, 524358, 536870914, 524359, 10, 524360, 10, 524361, 10, 524362, 10, 524363, 10, 524364, 10, 524365, 10, 524366, 10, 589824, 10, 589825, 13, 589840, 536870914, 589841, 10, 589842, 10, 589843, 10, 589844, 2, 589862, 7, 589865, 7, 589876, 536870913, 589877, 6, 589878, 1, 589894, 536870914, 589895, 10, 589896, 10, 589897, 10, 589898, 10, 589899, 10, 589900, 10, 589901, 10, 589902, 10, 655360, 2, 655376, 536870914, 655377, 10, 655378, 10, 655379, 10, 655380, 2, 655398, 7, 655401, 8, 655412, 536870925, 655413, 11, 655414, 13, 655430, 536870914, 655431, 10, 655432, 10, 655433, 10, 655434, 10, 655435, 10, 655436, 10, 655437, 10, 655438, 10, 720896, 2, 720912, 536870914, 720913, 10, 720914, 10, 720915, 10, 720916, 2, 720934, 8, 720937, 7, 720958, 536870913, 720959, 5, 720960, 536870917, 720961, 5, 720962, 5, 720963, 536870917, 720964, 5, 720965, 0, 720966, 536870916, 720967, 10, 720968, 10, 720969, 10, 720970, 10, 720971, 10, 720972, 10, 720973, 10, 720974, 10, 786432, 2, 786437, 9, 786448, 536870914, 786449, 10, 786450, 10, 786451, 10, 786452, 2, 786464, 536870913, 786465, 1, 786470, 7, 786473, 7, 786474, 536870924, 786475, 1, 786494, 536870914, 786495, 10, 786496, 10, 786497, 10, 786498, 10, 786499, 10, 786500, 10, 786501, 10, 786502, 10, 786503, 10, 786504, 10, 786505, 10, 786506, 10, 786507, 10, 786508, 10, 786509, 10, 851968, 2, 851973, 7, 851984, 536870914, 851985, 10, 851986, 10, 851987, 10, 851988, 2, 851996, 536870913, 851997, 1, 852000, 536870914, 852001, 3, 852006, 7, 852009, 536870913, 852011, 2, 852030, 536870914, 852031, 10, 852032, 10, 852033, 10, 852034, 10, 852035, 10, 852036, 10, 852037, 10, 852038, 10, 852039, 10, 852040, 10, 852041, 10, 852042, 10, 852043, 10, 852044, 10, 852045, 10, 917504, 2, 917506, 9, 917509, 7, 917512, 536870921, 917520, 536870925, 917521, 11, 917522, 11, 917523, 11, 917524, 13, 917532, 536870925, 917533, 13, 917536, 536870914, 917537, 4, 917538, 1, 917540, 536870913, 917541, 0, 917542, 1, 917545, 536870914, 917546, 10, 917547, 4, 917548, 1, 917566, 536870914, 917567, 10, 917568, 10, 917569, 10, 917570, 10, 917571, 10, 917572, 10, 917573, 10, 917574, 10, 917575, 10, 917576, 10, 917577, 10, 917578, 10, 917579, 10, 917580, 10, 917581, 10, 983040, 2, 983042, 7, 983045, 7, 983048, 536870920, 983050, 536870913, 983051, 1, 983064, 536870913, 983065, 1, 983072, 536870914, 983073, 10, 983074, 4, 983075, 0, 983076, 536870916, 983077, 10, 983078, 4, 983079, 536870912, 983080, 536870912, 983081, 536870916, 983082, 10, 983083, 10, 983084, 2, 983095, 9, 983102, 536870914, 983103, 10, 983104, 10, 983105, 10, 983106, 10, 983107, 10, 983108, 10, 983109, 10, 983110, 10, 983111, 10, 983112, 10, 983113, 10, 983114, 10, 983115, 10, 983116, 10, 983117, 10, 1048576, 2, 1048578, 8, 1048581, 8, 1048584, 536870919, 1048586, 536870925, 1048587, 13, 1048600, 536870925, 1048601, 13, 1048604, 9, 1048608, 536870925, 1048609, 536870923, 1048610, 536870923, 1048611, 536870923, 1048612, 10, 1048613, 10, 1048614, 10, 1048615, 10, 1048616, 10, 1048617, 10, 1048618, 10, 1048619, 10, 1048620, 4, 1048621, 1, 1048630, 536870921, 1048631, 8, 1048638, 536870914, 1048639, 10, 1048640, 10, 1048641, 10, 1048642, 10, 1048643, 10, 1048644, 10, 1048645, 10, 1048646, 10, 1048647, 10, 1048648, 10, 1048649, 10, 1048650, 10, 1048651, 10, 1048652, 10, 1048653, 10, 1114112, 4, 1114113, 0, 1114114, 6, 1114115, 0, 1114116, 0, 1114117, 6, 1114118, 1, 1114120, 536870920, 1114128, 536870913, 1114129, 5, 1114130, 536870917, 1114131, 5, 1114132, 0, 1114133, 1, 1114140, 7, 1114141, 536870921, 1114148, 536870914, 1114149, 10, 1114150, 10, 1114151, 10, 1114152, 10, 1114153, 10, 1114154, 10, 1114155, 10, 1114156, 10, 1114157, 2, 1114166, 536870920, 1114167, 8, 1114174, 536870914, 1114175, 10, 1114176, 10, 1114177, 10, 1114178, 10, 1114179, 10, 1114180, 10, 1114181, 10, 1114182, 10, 1114183, 10, 1114184, 10, 1114185, 10, 1114186, 10, 1114187, 10, 1114188, 10, 1179648, 10, 1179649, 10, 1179650, 10, 1179651, 10, 1179652, 10, 1179653, 10, 1179654, 2, 1179656, 536870919, 1179663, 536870915, 1179665, 10, 1179666, 10, 1179667, 10, 1179668, 10, 1179669, 4, 1179670, 12, 1179675, 9, 1179676, 8, 1179677, 8, 1179684, 536870914, 1179685, 10, 1179686, 10, 1179687, 10, 1179688, 10, 1179689, 10, 1179690, 10, 1179691, 10, 1179692, 10, 1179693, 4, 1179694, 1, 1179701, 9, 1179702, 536870919, 1179703, 7, 1179710, 536870914, 1179711, 10, 1179712, 10, 1179713, 10, 1179714, 10, 1179715, 10, 1179716, 10, 1179717, 10, 1179718, 10, 1179719, 10, 1179720, 10, 1179721, 10, 1179722, 10, 1245184, 10, 1245185, 10, 1245186, 10, 1245187, 10, 1245188, 10, 1245189, 10, 1245190, 2, 1245192, 536870919, 1245199, 536870913, 1245200, 536870916, 1245201, 10, 1245202, 10, 1245203, 10, 1245204, 10, 1245205, 10, 1245207, 1, 1245211, 7, 1245212, 7, 1245213, 536870920, 1245220, 536870914, 1245221, 10, 1245222, 10, 1245223, 10, 1245224, 10, 1245225, 10, 1245226, 10, 1245227, 10, 1245228, 10, 1245229, 10, 1245230, 2, 1245237, 8, 1245238, 536870919, 1245239, 8, 1245240, 536870921, 1245246, 536870914, 1245247, 10, 1245248, 10, 1245249, 10, 1245250, 10, 1245251, 10, 1245252, 10, 1245253, 10, 1245254, 10, 1245255, 10, 1245256, 10, 1245257, 10, 1245258, 10, 1310720, 10, 1310721, 10, 1310722, 10, 1310723, 10, 1310724, 10, 1310725, 10, 1310726, 2, 1310728, 536870920, 1310730, 536870913, 1310731, 1, 1310734, 536870913, 1310735, 536870916, 1310736, 10, 1310737, 10, 1310738, 10, 1310739, 10, 1310740, 10, 1310741, 10, 1310742, 10, 1310743, 4, 1310744, 1, 1310747, 8, 1310748, 7, 1310749, 536870919, 1310756, 536870914, 1310757, 10, 1310758, 10, 1310759, 10, 1310760, 10, 1310761, 10, 1310762, 10, 1310763, 10, 1310764, 10, 1310765, 10, 1310766, 4, 1310767, 5, 1310768, 12, 1310773, 7, 1310774, 536870919, 1310775, 7, 1310776, 536870919, 1310782, 536870914, 1310783, 10, 1310784, 10, 1310785, 10, 1310786, 10, 1310787, 10, 1310788, 10, 1310789, 10, 1310790, 10, 1310791, 10, 1310792, 10, 1310793, 10, 1376256, 10, 1376257, 10, 1376258, 10, 1376259, 10, 1376260, 10, 1376261, 10, 1376262, 4, 1376263, 0, 1376264, 0, 1376265, 0, 1376266, 536870916, 1376267, 4, 1376268, 0, 1376269, 0, 1376270, 536870916, 1376271, 10, 1376272, 10, 1376273, 10, 1376274, 10, 1376275, 10, 1376276, 10, 1376277, 10, 1376278, 10, 1376279, 10, 1376280, 4, 1376281, 12, 1376283, 8, 1376284, 8, 1376285, 536870920, 1376287, 536870924, 1376288, 0, 1376289, 5, 1376290, 536870917, 1376291, 0, 1376292, 536870916, 1376293, 10, 1376294, 10, 1376295, 10, 1376296, 10, 1376297, 10, 1376298, 10, 1376299, 10, 1376300, 10, 1376301, 10, 1376302, 10, 1376303, 10, 1376305, 12, 1376309, 7, 1376310, 536870920, 1376311, 7, 1376312, 536870920, 1376318, 536870914, 1376319, 10, 1376320, 10, 1376321, 10, 1376322, 10, 1376323, 10, 1376324, 10, 1376325, 10, 1376326, 10, 1376327, 10, 1376328, 10, 1441792, 10, 1441793, 10, 1441794, 10, 1441795, 10, 1441796, 10, 1441797, 10, 1441798, 10, 1441799, 10, 1441800, 10, 1441801, 10, 1441802, 10, 1441803, 10, 1441804, 10, 1441805, 10, 1441806, 10, 1441807, 10, 1441808, 10, 1441809, 10, 1441810, 10, 1441811, 10, 1441812, 10, 1441813, 10, 1441814, 10, 1441815, 10, 1441816, 10, 1441818, 0, 1441819, 6, 1441820, 6, 1441821, 536870918, 1441822, 5, 1441824, 10, 1441825, 10, 1441826, 10, 1441827, 10, 1441828, 10, 1441829, 10, 1441830, 10, 1441831, 10, 1441832, 10, 1441833, 10, 1441834, 10, 1441835, 10, 1441836, 10, 1441837, 10, 1441838, 10, 1441839, 10, 1441840, 10, 1441842, 0, 1441843, 0, 1441844, 0, 1441845, 6, 1441846, 536870918, 1441847, 6, 1441848, 536870918, 1441849, 0, 1441850, 5, 1441851, 536870917, 1441852, 5, 1441853, 0, 1441854, 536870916, 1441855, 10, 1441856, 10, 1441857, 10, 1441858, 10, 1441859, 10, 1441860, 10, 1441861, 10, 1441862, 10, 1441863, 10, 1507328, 10, 1507329, 10, 1507330, 10, 1507331, 10, 1507332, 10, 1507333, 10, 1507334, 10, 1507335, 10, 1507336, 10, 1507337, 10, 1507338, 10, 1507339, 10, 1507340, 10, 1507341, 10, 1507342, 10, 1507343, 10, 1507344, 10, 1507345, 10, 1507346, 10, 1507347, 10, 1507348, 10, 1507349, 10, 1507350, 10, 1507351, 10, 1507352, 10, 1507353, 10, 1507354, 10, 1507355, 10, 1507356, 10, 1507357, 10, 1507358, 10, 1507359, 10, 1507360, 10, 1507361, 10, 1507362, 10, 1507363, 10, 1507364, 10, 1507365, 10, 1507366, 10, 1507367, 10, 1507368, 10, 1507369, 10, 1507370, 10, 1507371, 10, 1507372, 10, 1507373, 10, 1507374, 10, 1507375, 10, 1507376, 10, 1507377, 10, 1507378, 10, 1507379, 10, 1507380, 10, 1507381, 10, 1507382, 10, 1507383, 10, 1507384, 10, 1507385, 10, 1507386, 10, 1507387, 10, 1507388, 10, 1507389, 10, 1507390, 10, 1507391, 10, 1507392, 10, 1507393, 10, 1507394, 10, 1507395, 10, 1507396, 10, 1507397, 10, 1507398, 10, 1507399, 10, 1572864, 10, 1572865, 10, 1572866, 10, 1572867, 10, 1572868, 10, 1572869, 10, 1572870, 10, 1572871, 10, 1572872, 10, 1572873, 10, 1572874, 10, 1572875, 10, 1572876, 10, 1572877, 10, 1572878, 10, 1572879, 10, 1572880, 10, 1572881, 10, 1572882, 10, 1572883, 10, 1572884, 10, 1572885, 10, 1572886, 10, 1572887, 10, 1572888, 10, 1572889, 10, 1572890, 10, 1572891, 10, 1572892, 10, 1572893, 10, 1572894, 10, 1572895, 10, 1572896, 10, 1572897, 10, 1572898, 10, 1572899, 10, 1572900, 10, 1572901, 10, 1572902, 10, 1572903, 10, 1572904, 10, 1572905, 10, 1572906, 10, 1572907, 10, 1572908, 10, 1572909, 10, 1572910, 10, 1572911, 10, 1572912, 10, 1572913, 10, 1572914, 10, 1572915, 10, 1572916, 10, 1572917, 10, 1572918, 10, 1572919, 10, 1572920, 10, 1572921, 10, 1572922, 10, 1572923, 10, 1572924, 10, 1572925, 10, 1572926, 10, 1572927, 10, 1572928, 10, 1572929, 10, 1572930, 10, 1572931, 10, 1572932, 10, 1572933, 10, 1572934, 10, 1572935, 10, 1638400, 10, 1638401, 10, 1638402, 10, 1638403, 10, 1638404, 10, 1638405, 10, 1638406, 10, 1638407, 10, 1638408, 10, 1638409, 10, 1638410, 10, 1638411, 10, 1638412, 10, 1638413, 10, 1638414, 10, 1638415, 10, 1638416, 10, 1638417, 10, 1638418, 10, 1638419, 10, 1638420, 10, 1638421, 10, 1638422, 10, 1638423, 10, 1638424, 10, 1638425, 10, 1638426, 10, 1638427, 10, 1638428, 10, 1638429, 10, 1638430, 10, 1638431, 10, 1638432, 10, 1638433, 10, 1638434, 10, 1638435, 10, 1638436, 10, 1638437, 10, 1638438, 10, 1638439, 10, 1638440, 10, 1638441, 10, 1638442, 10, 1638443, 10, 1638444, 10, 1638445, 10, 1638446, 10, 1638447, 10, 1638448, 10, 1638449, 10, 1638450, 10, 1638451, 10, 1638452, 10, 1638453, 10, 1638454, 10, 1638455, 10, 1638456, 10, 1638457, 10, 1638458, 10, 1638459, 10, 1638460, 10, 1638461, 10, 1638462, 10, 1638463, 10, 1638464, 10, 1638465, 10, 1638466, 10, 1638467, 10, 1638468, 10, 1638469, 10, 1638470, 10, 1638471, 10, 1703952, 10, 1703953, 10, 1703954, 10, 1703955, 10, 1703956, 10, 1703957, 10, 1703958, 10, 1703959, 10, 1703960, 10, 1703961, 10, 1703962, 10, 1703963, 10, 1703964, 10, 1703965, 10, 1703966, 10, 1703967, 10, 1703968, 10, 1703969, 10, 1703970, 10, 1703971, 10, 1703972, 10, 1703973, 10, 1703974, 10, 1703975, 10, 1703976, 10, 1703977, 10, 1703978, 10, 1703979, 10, 1703980, 10, 1703981, 10, 1703982, 10, 1703983, 10, 1703984, 10, 1703985, 10, 1703986, 10, 1703987, 10, 1703988, 10, 1703989, 10, 1703990, 10, 1703991, 10, 1703992, 10, 1703993, 10, 1703994, 10, 1703995, 10, 1703996, 10, 1703997, 10, 1703998, 10, 1703999, 10, 1704000, 10, 1704001, 10, 1704002, 10, 1704003, 10, 1704004, 10, 1704005, 10, 1704006, 10, 1704007, 10, 1769488, 10, 1769489, 10, 1769490, 10, 1769491, 10, 1769492, 10, 1769493, 10, 1769494, 10, 1769495, 10, 1769496, 10, 1769497, 10, 1769498, 10, 1769499, 10, 1769500, 10, 1769501, 10, 1769502, 10, 1769503, 10, 1769504, 10, 1769505, 10, 1769506, 10, 1769507, 10, 1769508, 10, 1769509, 10, 1769510, 10, 1769511, 10, 1769512, 10, 1769513, 10, 1769514, 10, 1769515, 10, 1769516, 10, 1769517, 10, 1769518, 10, 1769519, 10, 1769520, 10, 1769521, 10, 1769522, 10, 1769523, 10, 1769524, 10, 1769525, 10, 1769526, 10, 1769527, 10, 1769528, 10, 1769529, 10, 1769530, 10, 1769531, 10, 1769532, 10, 1769533, 10, 1769534, 10, 1769535, 10, 1769536, 10, 1769537, 10, 1769538, 10, 1769539, 10, 1769540, 10, 1769541, 10 </int_array>
<dictionary shared="false">
<string> "_edit_lock_" </string>
@@ -483,12 +487,10 @@
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
- <string> "deflight_rot_y" </string>
- <real> 0.628319 </real>
- <string> "zfar" </string>
- <real> 500 </real>
<string> "fov" </string>
<real> 45 </real>
+ <string> "zfar" </string>
+ <real> 500 </real>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
@@ -556,6 +558,8 @@
<vector3> 0, 0, 0 </vector3>
</dictionary>
</array>
+ <string> "deflight_rot_y" </string>
+ <real> 0.628319 </real>
<string> "default_light" </string>
<bool> True </bool>
<string> "viewport_mode" </string>
@@ -806,7 +810,6 @@
<string> "2D" </string>
</dictionary>
<resource resource_type="AudioStream" path="res://music.ogg"> </resource>
- <bool> False </bool>
<real> 2 </real>
<resource resource_type="PackedScene" path="res://enemy.xml"> </resource>
<vector2> 834.664, 1309.6 </vector2>
@@ -1000,7 +1003,7 @@
<real> -1 </real>
</array>
<string> "nodes" </string>
- <int_array len="952"> -1, -1, 1, 0, -1, 2, 2, 0, 3, 1, 0, 0, 0, 5, 4, -1, 21, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 2, 14, 7, 15, 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 7, 21, 3, 22, 5, 23, 13, 24, 14, 3, 15, 0, 0, 0, 1, 25, -1, 2, 2, 0, 3, 16, 0, 2, 0, 27, 26, 17, 3, 2, 0, 9, 18, 3, 19, 0, 2, 0, 27, 28, 17, 3, 2, 0, 9, 20, 3, 19, 0, 2, 0, 27, 29, 17, 3, 2, 0, 9, 21, 3, 19, 0, 2, 0, 27, 30, 17, 3, 2, 0, 9, 22, 3, 19, 0, 2, 0, 27, 31, 17, 3, 2, 0, 9, 23, 3, 19, 0, 2, 0, 27, 32, 17, 3, 2, 0, 9, 24, 3, 19, 0, 2, 0, 27, 33, 17, 3, 2, 0, 9, 25, 3, 19, 0, 2, 0, 27, 34, 17, 3, 2, 0, 9, 26, 3, 19, 0, 2, 0, 27, 35, 17, 3, 2, 0, 9, 27, 3, 19, 0, 2, 0, 27, 36, 17, 3, 2, 0, 9, 28, 3, 19, 0, 2, 0, 27, 37, 17, 3, 2, 0, 9, 29, 3, 19, 0, 2, 0, 27, 38, 17, 3, 2, 0, 9, 30, 3, 19, 0, 2, 0, 27, 39, 17, 3, 2, 0, 9, 31, 3, 19, 0, 2, 0, 27, 40, 17, 3, 2, 0, 9, 32, 3, 19, 0, 2, 0, 27, 41, 17, 3, 2, 0, 9, 33, 3, 19, 0, 2, 0, 27, 42, 17, 3, 2, 0, 9, 34, 3, 19, 0, 2, 0, 27, 43, 17, 3, 2, 0, 9, 35, 3, 19, 0, 2, 0, 27, 44, 17, 3, 2, 0, 9, 36, 3, 19, 0, 2, 0, 27, 45, 17, 3, 2, 0, 9, 37, 3, 19, 0, 2, 0, 27, 46, 17, 3, 2, 0, 9, 38, 3, 19, 0, 2, 0, 27, 47, 17, 3, 2, 0, 9, 39, 3, 19, 0, 2, 0, 27, 48, 17, 3, 2, 0, 9, 40, 3, 19, 0, 2, 0, 27, 49, 17, 3, 2, 0, 9, 41, 3, 19, 0, 2, 0, 27, 50, 17, 3, 2, 0, 9, 42, 3, 19, 0, 2, 0, 27, 51, 17, 3, 2, 0, 9, 43, 3, 19, 0, 2, 0, 27, 52, 17, 3, 2, 0, 9, 44, 3, 19, 0, 2, 0, 27, 53, 17, 3, 2, 0, 9, 45, 3, 19, 0, 2, 0, 27, 54, 17, 3, 2, 0, 9, 46, 3, 19, 0, 2, 0, 27, 55, 17, 3, 2, 0, 9, 47, 3, 19, 0, 2, 0, 27, 56, 17, 3, 2, 0, 9, 48, 3, 19, 0, 2, 0, 27, 57, 17, 3, 2, 0, 9, 49, 3, 19, 0, 2, 0, 27, 58, 17, 3, 2, 0, 9, 50, 3, 19, 0, 2, 0, 27, 59, 17, 3, 2, 0, 9, 51, 3, 19, 0, 2, 0, 27, 60, 17, 3, 2, 0, 9, 52, 3, 19, 0, 2, 0, 27, 61, 17, 3, 2, 0, 9, 53, 3, 19, 0, 2, 0, 27, 62, 17, 3, 2, 0, 9, 54, 3, 19, 0, 2, 0, 27, 63, 17, 3, 2, 0, 9, 55, 3, 19, 0, 2, 0, 27, 64, 17, 3, 2, 0, 9, 56, 3, 19, 0, 2, 0, 27, 65, 17, 3, 2, 0, 9, 57, 3, 19, 0, 2, 0, 27, 66, 17, 3, 2, 0, 9, 58, 3, 19, 0, 2, 0, 27, 67, 17, 3, 2, 0, 9, 59, 3, 19, 0, 2, 0, 27, 68, 17, 3, 2, 0, 9, 60, 3, 19, 0, 0, 0, 70, 69, 61, 3, 2, 0, 9, 62, 3, 63, 0, 0, 0, 1, 71, -1, 1, 2, 0, 0, 46, 0, 73, 72, 64, 5, 2, 0, 9, 65, 3, 66, 74, 67, 75, 68, 0, 46, 0, 73, 76, 64, 5, 2, 0, 9, 69, 3, 66, 74, 70, 75, 71, 0, 46, 0, 73, 77, 64, 5, 2, 0, 9, 72, 3, 66, 74, 73, 75, 71, 0, 46, 0, 73, 78, 74, 3, 2, 0, 9, 75, 3, 76, 0, 0, 0, 80, 79, -1, 7, 2, 0, 81, 77, 82, 78, 83, 2, 84, 79, 85, 2, 86, 78, 0, 0, 0, 1, 87, -1, 1, 2, 0, 0, 52, 0, 70, 88, 80, 3, 2, 0, 9, 81, 3, 82, 0, 52, 0, 70, 89, 80, 3, 2, 0, 9, 83, 3, 82, 0, 52, 0, 70, 90, 80, 3, 2, 0, 9, 84, 3, 82, 0, 52, 0, 70, 91, 80, 3, 2, 0, 9, 85, 3, 82, 0, 52, 0, 70, 92, 80, 3, 2, 0, 9, 86, 3, 82, 0, 52, 0, 70, 93, 80, 3, 2, 0, 9, 87, 3, 82, 0, 52, 0, 70, 94, 80, 3, 2, 0, 9, 88, 3, 82, 0, 52, 0, 70, 95, 80, 3, 2, 0, 9, 89, 3, 82, 0, 52, 0, 70, 96, 80, 3, 2, 0, 9, 90, 3, 82, 0, 52, 0, 70, 97, 80, 3, 2, 0, 9, 91, 3, 82, 0, 52, 0, 70, 98, 80, 3, 2, 0, 9, 92, 3, 82, 0, 0, 0, 100, 99, 93, 2, 2, 0, 3, 94, 0, 0, 0, 101, 101, -1, 29, 2, 0, 6, 2, 7, 3, 8, 3, 102, 95, 103, 96, 104, 97, 105, 98, 106, 0, 107, 0, 108, 0, 109, 0, 110, 2, 111, 2, 112, 12, 113, 3, 114, 5, 115, 99, 116, 3, 117, 100, 118, 5, 119, 78, 120, 78, 121, 101, 122, 7, 123, 7, 124, 2, 125, 78, 126, 102, 0 </int_array>
+ <int_array len="960"> -1, -1, 1, 0, -1, 2, 2, 0, 3, 1, 0, 0, 0, 5, 4, -1, 24, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 2, 15, 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 8, 22, 14, 23, 14, 24, 3, 25, 6, 26, 4, 27, 15, 3, 16, 0, 0, 0, 1, 28, -1, 2, 2, 0, 3, 17, 0, 2, 0, 30, 29, 18, 3, 2, 0, 10, 19, 3, 20, 0, 2, 0, 30, 31, 18, 3, 2, 0, 10, 21, 3, 20, 0, 2, 0, 30, 32, 18, 3, 2, 0, 10, 22, 3, 20, 0, 2, 0, 30, 33, 18, 3, 2, 0, 10, 23, 3, 20, 0, 2, 0, 30, 34, 18, 3, 2, 0, 10, 24, 3, 20, 0, 2, 0, 30, 35, 18, 3, 2, 0, 10, 25, 3, 20, 0, 2, 0, 30, 36, 18, 3, 2, 0, 10, 26, 3, 20, 0, 2, 0, 30, 37, 18, 3, 2, 0, 10, 27, 3, 20, 0, 2, 0, 30, 38, 18, 3, 2, 0, 10, 28, 3, 20, 0, 2, 0, 30, 39, 18, 3, 2, 0, 10, 29, 3, 20, 0, 2, 0, 30, 40, 18, 3, 2, 0, 10, 30, 3, 20, 0, 2, 0, 30, 41, 18, 3, 2, 0, 10, 31, 3, 20, 0, 2, 0, 30, 42, 18, 3, 2, 0, 10, 32, 3, 20, 0, 2, 0, 30, 43, 18, 3, 2, 0, 10, 33, 3, 20, 0, 2, 0, 30, 44, 18, 3, 2, 0, 10, 34, 3, 20, 0, 2, 0, 30, 45, 18, 3, 2, 0, 10, 35, 3, 20, 0, 2, 0, 30, 46, 18, 3, 2, 0, 10, 36, 3, 20, 0, 2, 0, 30, 47, 18, 3, 2, 0, 10, 37, 3, 20, 0, 2, 0, 30, 48, 18, 3, 2, 0, 10, 38, 3, 20, 0, 2, 0, 30, 49, 18, 3, 2, 0, 10, 39, 3, 20, 0, 2, 0, 30, 50, 18, 3, 2, 0, 10, 40, 3, 20, 0, 2, 0, 30, 51, 18, 3, 2, 0, 10, 41, 3, 20, 0, 2, 0, 30, 52, 18, 3, 2, 0, 10, 42, 3, 20, 0, 2, 0, 30, 53, 18, 3, 2, 0, 10, 43, 3, 20, 0, 2, 0, 30, 54, 18, 3, 2, 0, 10, 44, 3, 20, 0, 2, 0, 30, 55, 18, 3, 2, 0, 10, 45, 3, 20, 0, 2, 0, 30, 56, 18, 3, 2, 0, 10, 46, 3, 20, 0, 2, 0, 30, 57, 18, 3, 2, 0, 10, 47, 3, 20, 0, 2, 0, 30, 58, 18, 3, 2, 0, 10, 48, 3, 20, 0, 2, 0, 30, 59, 18, 3, 2, 0, 10, 49, 3, 20, 0, 2, 0, 30, 60, 18, 3, 2, 0, 10, 50, 3, 20, 0, 2, 0, 30, 61, 18, 3, 2, 0, 10, 51, 3, 20, 0, 2, 0, 30, 62, 18, 3, 2, 0, 10, 52, 3, 20, 0, 2, 0, 30, 63, 18, 3, 2, 0, 10, 53, 3, 20, 0, 2, 0, 30, 64, 18, 3, 2, 0, 10, 54, 3, 20, 0, 2, 0, 30, 65, 18, 3, 2, 0, 10, 55, 3, 20, 0, 2, 0, 30, 66, 18, 3, 2, 0, 10, 56, 3, 20, 0, 2, 0, 30, 67, 18, 3, 2, 0, 10, 57, 3, 20, 0, 2, 0, 30, 68, 18, 3, 2, 0, 10, 58, 3, 20, 0, 2, 0, 30, 69, 18, 3, 2, 0, 10, 59, 3, 20, 0, 2, 0, 30, 70, 18, 3, 2, 0, 10, 60, 3, 20, 0, 2, 0, 30, 71, 18, 3, 2, 0, 10, 61, 3, 20, 0, 0, 0, 73, 72, 62, 3, 2, 0, 10, 63, 3, 64, 0, 0, 0, 1, 74, -1, 1, 2, 0, 0, 46, 0, 76, 75, 65, 5, 2, 0, 10, 66, 3, 67, 77, 68, 78, 69, 0, 46, 0, 76, 79, 65, 5, 2, 0, 10, 70, 3, 67, 77, 71, 78, 72, 0, 46, 0, 76, 80, 65, 5, 2, 0, 10, 73, 3, 67, 77, 74, 78, 72, 0, 46, 0, 76, 81, 75, 3, 2, 0, 10, 76, 3, 77, 0, 0, 0, 83, 82, -1, 7, 2, 0, 84, 78, 85, 14, 86, 2, 87, 79, 88, 2, 89, 14, 0, 0, 0, 1, 90, -1, 1, 2, 0, 0, 52, 0, 73, 91, 80, 3, 2, 0, 10, 81, 3, 82, 0, 52, 0, 73, 92, 80, 3, 2, 0, 10, 83, 3, 82, 0, 52, 0, 73, 93, 80, 3, 2, 0, 10, 84, 3, 82, 0, 52, 0, 73, 94, 80, 3, 2, 0, 10, 85, 3, 82, 0, 52, 0, 73, 95, 80, 3, 2, 0, 10, 86, 3, 82, 0, 52, 0, 73, 96, 80, 3, 2, 0, 10, 87, 3, 82, 0, 52, 0, 73, 97, 80, 3, 2, 0, 10, 88, 3, 82, 0, 52, 0, 73, 98, 80, 3, 2, 0, 10, 89, 3, 82, 0, 52, 0, 73, 99, 80, 3, 2, 0, 10, 90, 3, 82, 0, 52, 0, 73, 100, 80, 3, 2, 0, 10, 91, 3, 82, 0, 52, 0, 73, 101, 80, 3, 2, 0, 10, 92, 3, 82, 0, 0, 0, 103, 102, 93, 2, 2, 0, 3, 94, 0, 0, 0, 104, 104, -1, 30, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 105, 95, 106, 96, 107, 97, 108, 98, 109, 0, 110, 0, 111, 0, 112, 0, 113, 2, 114, 2, 115, 13, 116, 3, 117, 6, 118, 99, 119, 3, 120, 100, 121, 6, 122, 14, 123, 14, 124, 101, 125, 8, 126, 8, 127, 2, 128, 14, 129, 102, 0 </int_array>
<string> "conns" </string>
<int_array len="0"> </int_array>
</dictionary>
diff --git a/demos/2d/screen_space_shaders/art/burano.jpg b/demos/2d/screen_space_shaders/art/burano.jpg
new file mode 100644
index 0000000000..cdab993ec1
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/burano.jpg
Binary files differ
diff --git a/demos/2d/screen_space_shaders/art/burano.png b/demos/2d/screen_space_shaders/art/burano.png
new file mode 100644
index 0000000000..6eec09d585
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/burano.png
Binary files differ
diff --git a/demos/2d/screen_space_shaders/art/filmgrain.png b/demos/2d/screen_space_shaders/art/filmgrain.png
new file mode 100644
index 0000000000..b8ea89902c
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/filmgrain.png
Binary files differ
diff --git a/demos/2d/screen_space_shaders/art/filmgrain.png.flags b/demos/2d/screen_space_shaders/art/filmgrain.png.flags
new file mode 100644
index 0000000000..d5476d5499
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/filmgrain.png.flags
@@ -0,0 +1 @@
+repeat=true
diff --git a/demos/2d/screen_space_shaders/art/forest.png b/demos/2d/screen_space_shaders/art/forest.png
new file mode 100644
index 0000000000..f5a2fb9bfb
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/forest.png
Binary files differ
diff --git a/demos/2d/screen_space_shaders/art/mountains.png b/demos/2d/screen_space_shaders/art/mountains.png
new file mode 100644
index 0000000000..b8435bb1a8
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/mountains.png
Binary files differ
diff --git a/demos/2d/screen_space_shaders/art/platformer.png b/demos/2d/screen_space_shaders/art/platformer.png
new file mode 100644
index 0000000000..21c1cb4c4b
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/platformer.png
Binary files differ
diff --git a/demos/2d/screen_space_shaders/art/vignette.png b/demos/2d/screen_space_shaders/art/vignette.png
new file mode 100644
index 0000000000..8afeb7f9e1
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/vignette.png
Binary files differ
diff --git a/demos/2d/screen_space_shaders/art/white.png b/demos/2d/screen_space_shaders/art/white.png
new file mode 100644
index 0000000000..573faa33f2
--- /dev/null
+++ b/demos/2d/screen_space_shaders/art/white.png
Binary files differ
diff --git a/demos/2d/screen_space_shaders/engine.cfg b/demos/2d/screen_space_shaders/engine.cfg
new file mode 100644
index 0000000000..2a41110886
--- /dev/null
+++ b/demos/2d/screen_space_shaders/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="Screen-Space Shaders"
+main_scene="res://screen_shaders.scn"
diff --git a/demos/2d/screen_space_shaders/screen_shaders.gd b/demos/2d/screen_space_shaders/screen_shaders.gd
new file mode 100644
index 0000000000..4e8a548539
--- /dev/null
+++ b/demos/2d/screen_space_shaders/screen_shaders.gd
@@ -0,0 +1,32 @@
+
+extends Control
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+func _ready():
+ # Initialization here
+ for c in get_node("pictures").get_children():
+ get_node("picture").add_item("PIC: "+c.get_name())
+ for c in get_node("effects").get_children():
+ get_node("effect").add_item("FX: "+c.get_name())
+ pass
+
+
+
+
+func _on_picture_item_selected( ID ):
+ for c in range(get_node("pictures").get_child_count()):
+ if (ID==c):
+ get_node("pictures").get_child(c).show()
+ else:
+ get_node("pictures").get_child(c).hide()
+
+
+func _on_effect_item_selected( ID ):
+ for c in range(get_node("effects").get_child_count()):
+ if (ID==c):
+ get_node("effects").get_child(c).show()
+ else:
+ get_node("effects").get_child(c).hide()
diff --git a/demos/2d/screen_space_shaders/screen_shaders.scn b/demos/2d/screen_space_shaders/screen_shaders.scn
new file mode 100644
index 0000000000..aa359616de
--- /dev/null
+++ b/demos/2d/screen_space_shaders/screen_shaders.scn
Binary files differ
diff --git a/demos/2d/sdf_font/KaushanScript-Regular.otf b/demos/2d/sdf_font/KaushanScript-Regular.otf
new file mode 100644
index 0000000000..bd29502100
--- /dev/null
+++ b/demos/2d/sdf_font/KaushanScript-Regular.otf
Binary files differ
diff --git a/demos/2d/sdf_font/engine.cfg b/demos/2d/sdf_font/engine.cfg
new file mode 100644
index 0000000000..bdf26ce741
--- /dev/null
+++ b/demos/2d/sdf_font/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="Signed Distance Field Font"
+main_scene="res://sdf.scn"
diff --git a/demos/2d/sdf_font/font.fnt b/demos/2d/sdf_font/font.fnt
new file mode 100644
index 0000000000..c2b6b0177d
--- /dev/null
+++ b/demos/2d/sdf_font/font.fnt
Binary files differ
diff --git a/demos/2d/sdf_font/sdf.scn b/demos/2d/sdf_font/sdf.scn
new file mode 100644
index 0000000000..89d6245bf0
--- /dev/null
+++ b/demos/2d/sdf_font/sdf.scn
Binary files differ
diff --git a/demos/2d/sprite_shaders/cubio.png b/demos/2d/sprite_shaders/cubio.png
new file mode 100644
index 0000000000..6f76220225
--- /dev/null
+++ b/demos/2d/sprite_shaders/cubio.png
Binary files differ
diff --git a/demos/2d/sprite_shaders/engine.cfg b/demos/2d/sprite_shaders/engine.cfg
new file mode 100644
index 0000000000..09f9a59566
--- /dev/null
+++ b/demos/2d/sprite_shaders/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="2D Shaders for Sprites"
+main_scene="res://sprite_shaders.scn"
diff --git a/demos/2d/sprite_shaders/sprite_shaders.scn b/demos/2d/sprite_shaders/sprite_shaders.scn
new file mode 100644
index 0000000000..7c36f2137c
--- /dev/null
+++ b/demos/2d/sprite_shaders/sprite_shaders.scn
Binary files differ
diff --git a/demos/2d/texscreen/bubble.png b/demos/2d/texscreen/bubble.png
new file mode 100644
index 0000000000..021abba601
--- /dev/null
+++ b/demos/2d/texscreen/bubble.png
Binary files differ
diff --git a/demos/2d/texscreen/bubbles.gd b/demos/2d/texscreen/bubbles.gd
new file mode 100644
index 0000000000..2ee227a928
--- /dev/null
+++ b/demos/2d/texscreen/bubbles.gd
@@ -0,0 +1,17 @@
+
+extends Control
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const MAX_BUBBLES=10
+
+func _ready():
+ # Initialization here
+ for i in range(MAX_BUBBLES):
+ var bubble = preload("res://lens.scn").instance()
+ add_child(bubble)
+ pass
+
+
diff --git a/demos/2d/texscreen/bubbles.scn b/demos/2d/texscreen/bubbles.scn
new file mode 100644
index 0000000000..779cba6930
--- /dev/null
+++ b/demos/2d/texscreen/bubbles.scn
Binary files differ
diff --git a/demos/2d/texscreen/burano.png b/demos/2d/texscreen/burano.png
new file mode 100644
index 0000000000..6eec09d585
--- /dev/null
+++ b/demos/2d/texscreen/burano.png
Binary files differ
diff --git a/demos/2d/texscreen/engine.cfg b/demos/2d/texscreen/engine.cfg
new file mode 100644
index 0000000000..58193c8c4a
--- /dev/null
+++ b/demos/2d/texscreen/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="Glass Bubbles (Texscreen)"
+main_scene="res://bubbles.scn"
diff --git a/demos/2d/texscreen/lens.gd b/demos/2d/texscreen/lens.gd
new file mode 100644
index 0000000000..2ccbfba497
--- /dev/null
+++ b/demos/2d/texscreen/lens.gd
@@ -0,0 +1,37 @@
+
+extends BackBufferCopy
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const MOTION_SPEED=150
+
+var vsize;
+var dir;
+
+func _process(delta):
+ var pos = get_pos() + dir * delta * MOTION_SPEED
+
+ if (pos.x<0):
+ dir.x=abs(dir.x)
+ elif (pos.x>vsize.x):
+ dir.x=-abs(dir.x)
+
+ if (pos.y<0):
+ dir.y=abs(dir.y)
+ elif (pos.y>vsize.y):
+ dir.y=-abs(dir.y)
+
+ set_pos(pos)
+
+func _ready():
+ vsize = get_viewport_rect().size
+ var pos = vsize * Vector2(randf(),randf());
+ set_pos(pos);
+ dir = Vector2(randf()*2.0-1,randf()*2.0-1).normalized()
+ set_process(true)
+
+ # Initialization here
+ pass
+
+
diff --git a/demos/2d/texscreen/lens.scn b/demos/2d/texscreen/lens.scn
new file mode 100644
index 0000000000..5c6f8b7af8
--- /dev/null
+++ b/demos/2d/texscreen/lens.scn
Binary files differ
diff --git a/demos/3d/kinematic_char/cubelib.res b/demos/3d/kinematic_char/cubelib.res
index 66b999d78d..27f2b9b3bd 100644
--- a/demos/3d/kinematic_char/cubelib.res
+++ b/demos/3d/kinematic_char/cubelib.res
Binary files differ
diff --git a/demos/3d/kinematic_char/level.scn b/demos/3d/kinematic_char/level.scn
index a276fe22e1..7ccb2430c1 100644
--- a/demos/3d/kinematic_char/level.scn
+++ b/demos/3d/kinematic_char/level.scn
Binary files differ
diff --git a/demos/gui/drag_and_drop/drag_and_drop.scn b/demos/gui/drag_and_drop/drag_and_drop.scn
new file mode 100644
index 0000000000..94a25cc53e
--- /dev/null
+++ b/demos/gui/drag_and_drop/drag_and_drop.scn
Binary files differ
diff --git a/demos/gui/drag_and_drop/drag_drop_script.gd b/demos/gui/drag_and_drop/drag_drop_script.gd
new file mode 100644
index 0000000000..21a737ce1a
--- /dev/null
+++ b/demos/gui/drag_and_drop/drag_drop_script.gd
@@ -0,0 +1,24 @@
+
+extends ColorPickerButton
+
+
+#virtual function
+func get_drag_data(pos):
+
+ #use another colorpicker as drag preview
+ var cpb = ColorPickerButton.new()
+ cpb.set_color( get_color() )
+ cpb.set_size(Vector2(50,50))
+ set_drag_preview(cpb)
+ #return color as drag data
+ return get_color()
+
+#virtual function
+func can_drop_data(pos, data):
+ return typeof(data)==TYPE_COLOR
+
+#virtual function
+func drop_data(pos, data):
+ set_color(data)
+
+
diff --git a/demos/gui/drag_and_drop/engine.cfg b/demos/gui/drag_and_drop/engine.cfg
new file mode 100644
index 0000000000..448939c61d
--- /dev/null
+++ b/demos/gui/drag_and_drop/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="Drag &amp; Drop (GUI)"
+main_scene="res://drag_and_drop.scn"
diff --git a/demos/misc/window_management/control.gd b/demos/misc/window_management/control.gd
new file mode 100644
index 0000000000..bca13c5a0c
--- /dev/null
+++ b/demos/misc/window_management/control.gd
@@ -0,0 +1,177 @@
+
+extends Control
+
+func _fixed_process(delta):
+
+ var modetext = "Mode:\n"
+
+ if(OS.is_fullscreen()):
+ modetext += "Fullscreen\n"
+ else:
+ modetext += "Windowed\n"
+
+ if(!OS.is_resizable()):
+ modetext += "FixedSize\n"
+
+ if(OS.is_minimized()):
+ modetext += "Minimized\n"
+
+ if(OS.is_maximized()):
+ modetext += "Maximized\n"
+
+ if(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED):
+ modetext += "MouseGrab\n"
+ get_node("Label_MouseGrab_KeyInfo").show()
+ else:
+ get_node("Label_MouseGrab_KeyInfo").hide()
+
+ get_node("Label_Mode").set_text(modetext)
+
+ get_node("Label_Position").set_text( str("Position:\n", OS.get_window_position() ) )
+
+ get_node("Label_Size").set_text(str("Size:\n", OS.get_window_size() ) )
+
+ get_node("Label_MousePosition").set_text(str("Mouse Position:\n", Input.get_mouse_pos() ) )
+
+ get_node("Label_Screen_Count").set_text( str("Screen_Count:\n", OS.get_screen_count() ) )
+
+ get_node("Label_Screen_Current").set_text( str("Screen:\n", OS.get_screen() ) )
+
+ get_node("Label_Screen0_Resolution").set_text( str("Screen0 Resolution:\n", OS.get_screen_size() ) )
+
+ get_node("Label_Screen0_Position").set_text(str("Screen0 Position:\n",OS.get_screen_position() ) )
+
+ if(OS.get_screen_count() > 1):
+ get_node("Button_Screen0").show()
+ get_node("Button_Screen1").show()
+ get_node("Label_Screen1_Resolution").show()
+ get_node("Label_Screen1_Position").show()
+ get_node("Label_Screen1_Resolution").set_text( str("Screen1 Resolution:\n", OS.get_screen_size(1) ) )
+ get_node("Label_Screen1_Position").set_text( str("Screen1 Position:\n", OS.get_screen_position(1) ) )
+ else:
+ get_node("Button_Screen0").hide()
+ get_node("Button_Screen1").hide()
+ get_node("Label_Screen1_Resolution").hide()
+ get_node("Label_Screen1_Position").hide()
+
+ get_node("Button_Fullscreen").set_pressed( OS.is_fullscreen() )
+ get_node("Button_FixedSize").set_pressed( !OS.is_resizable() )
+ get_node("Button_Minimized").set_pressed( OS.is_minimized() )
+ get_node("Button_Maximized").set_pressed( OS.is_maximized() )
+ get_node("Button_Mouse_Grab").set_pressed( Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED )
+
+
+func check_wm_api():
+ var s = ""
+ if( !OS.has_method("get_screen_count") ):
+ s += " - get_screen_count()\n"
+
+ if( !OS.has_method("get_screen") ):
+ s += " - get_screen()\n"
+
+ if( !OS.has_method("set_screen") ):
+ s += " - set_screen()\n"
+
+ if( !OS.has_method("get_screen_position") ):
+ s += " - get_screen_position()\n"
+
+ if( !OS.has_method("get_screen_size") ):
+ s += " - get_screen_size()\n"
+
+ if( !OS.has_method("get_window_position") ):
+ s += " - get_window_position()\n"
+
+ if( !OS.has_method("set_window_position") ):
+ s += " - set_window_position()\n"
+
+ if( !OS.has_method("get_window_size") ):
+ s += " - get_window_size()\n"
+
+ if( !OS.has_method("set_window_size") ):
+ s += " - set_window_size()\n"
+
+ if( !OS.has_method("set_fullscreen") ):
+ s += " - set_fullscreen()\n"
+
+ if( !OS.has_method("is_fullscreen") ):
+ s += " - is_fullscreen()\n"
+
+ if( !OS.has_method("set_resizable") ):
+ s += " - set_resizable()\n"
+
+ if( !OS.has_method("is_resizable") ):
+ s += " - is_resizable()\n"
+
+ if( !OS.has_method("set_minimized") ):
+ s += " - set_minimized()\n"
+
+ if( !OS.has_method("is_minimized") ):
+ s += " - is_minimized()\n"
+
+ if( !OS.has_method("set_maximized") ):
+ s += " - set_maximized()\n"
+
+ if( !OS.has_method("is_maximized") ):
+ s += " - is_maximized()\n"
+
+ if( s.length() == 0 ):
+ return true
+ else:
+ var text = get_node("ImplementationDialog/Text").get_text()
+ get_node("ImplementationDialog/Text").set_text( text + s )
+ get_node("ImplementationDialog").show()
+ return false
+
+
+func _ready():
+ if( check_wm_api() ):
+ set_fixed_process(true)
+
+
+func _on_Button_MoveTo_pressed():
+ OS.set_window_position( Vector2(100,100) )
+
+
+func _on_Button_Resize_pressed():
+ OS.set_window_size( Vector2(1024,768) )
+
+
+func _on_Button_Screen0_pressed():
+ OS.set_screen(0)
+
+
+func _on_Button_Screen1_pressed():
+ OS.set_screen(1)
+
+
+func _on_Button_Fullscreen_pressed():
+ if(OS.is_fullscreen()):
+ OS.set_fullscreen(false)
+ else:
+ OS.set_fullscreen(true)
+
+
+func _on_Button_FixedSize_pressed():
+ if(OS.is_resizable()):
+ OS.set_resizable(false)
+ else:
+ OS.set_resizable(true)
+
+
+func _on_Button_Minimized_pressed():
+ if(OS.is_minimized()):
+ OS.set_minimized(false)
+ else:
+ OS.set_minimized(true)
+
+
+func _on_Button_Maximized_pressed():
+ if(OS.is_maximized()):
+ OS.set_maximized(false)
+ else:
+ OS.set_maximized(true)
+
+
+func _on_Button_Mouse_Grab_pressed():
+ var observer = get_node("../Observer")
+ observer.state = observer.STATE_GRAB
diff --git a/demos/misc/window_management/engine.cfg b/demos/misc/window_management/engine.cfg
new file mode 100644
index 0000000000..c53bd45fb7
--- /dev/null
+++ b/demos/misc/window_management/engine.cfg
@@ -0,0 +1,19 @@
+[application]
+
+name="window_management"
+main_scene="res://window_management.scn"
+icon="icon.png"
+
+[display]
+
+fullscreen=false
+resizable=true
+width=800
+height=600
+
+[input]
+
+move_forward=[key(W)]
+move_backwards=[key(S)]
+move_left=[key(A)]
+move_right=[key(D)]
diff --git a/demos/misc/window_management/icon.png b/demos/misc/window_management/icon.png
new file mode 100644
index 0000000000..0c422e37b0
--- /dev/null
+++ b/demos/misc/window_management/icon.png
Binary files differ
diff --git a/demos/misc/window_management/icon.png.flags b/demos/misc/window_management/icon.png.flags
new file mode 100644
index 0000000000..5130fd1aab
--- /dev/null
+++ b/demos/misc/window_management/icon.png.flags
@@ -0,0 +1 @@
+gen_mipmaps=false
diff --git a/demos/misc/window_management/observer/observer.gd b/demos/misc/window_management/observer/observer.gd
new file mode 100644
index 0000000000..d27912a670
--- /dev/null
+++ b/demos/misc/window_management/observer/observer.gd
@@ -0,0 +1,79 @@
+
+extends Spatial
+
+var r_pos = Vector2()
+var state
+
+const STATE_MENU=0
+const STATE_GRAB=1
+
+func direction(vector):
+ var v = get_node("Camera").get_global_transform().basis * vector
+ v = v.normalized()
+
+ return v
+
+
+func impulse(event, action):
+ if(event.is_action(action) && event.is_pressed() && !event.is_echo()):
+ return true
+ else:
+ return false
+
+
+func _fixed_process(delta):
+
+ if(state != STATE_GRAB):
+ return
+
+ if(Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED):
+ Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
+
+ var dir = Vector3()
+ var cam = get_global_transform()
+ var org = get_translation()
+
+ if (Input.is_action_pressed("move_forward")):
+ dir += direction(Vector3(0,0,-1))
+ if (Input.is_action_pressed("move_backwards")):
+ dir += direction(Vector3(0,0,1))
+ if (Input.is_action_pressed("move_left")):
+ dir += direction(Vector3(-1,0,0))
+ if (Input.is_action_pressed("move_right")):
+ dir += direction(Vector3(1,0,0))
+
+ dir = dir.normalized()
+
+ move(dir * 10 * delta)
+ var d = delta * 0.1
+
+ var yaw = get_transform().rotated(Vector3(0,1,0), d * r_pos.x)
+ set_transform(yaw)
+
+ var cam = get_node("Camera")
+ var pitch = cam.get_transform().rotated(Vector3(1,0,0), d * r_pos.y)
+ cam.set_transform(pitch)
+
+ r_pos.x = 0.0
+ r_pos.y = 0.0
+
+
+func _input( event ):
+ if(event.type == InputEvent.MOUSE_MOTION):
+ r_pos = event.relative_pos
+
+ if(impulse(event, "ui_cancel")):
+ if(state == STATE_GRAB):
+ Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
+ state = STATE_MENU
+ else:
+ Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
+ state = STATE_GRAB
+
+
+func _ready():
+ set_fixed_process(true)
+ set_process_input(true)
+
+ state = STATE_MENU
+
diff --git a/demos/misc/window_management/observer/observer.scn b/demos/misc/window_management/observer/observer.scn
new file mode 100644
index 0000000000..da29ad62b8
--- /dev/null
+++ b/demos/misc/window_management/observer/observer.scn
Binary files differ
diff --git a/demos/misc/window_management/window_management.scn b/demos/misc/window_management/window_management.scn
new file mode 100644
index 0000000000..b8b0ee210b
--- /dev/null
+++ b/demos/misc/window_management/window_management.scn
Binary files differ
diff --git a/demos/viewport/gui_in_3d/gui_3d.gd b/demos/viewport/gui_in_3d/gui_3d.gd
index 5309db9acb..c2a9df0069 100644
--- a/demos/viewport/gui_in_3d/gui_3d.gd
+++ b/demos/viewport/gui_in_3d/gui_3d.gd
@@ -7,38 +7,39 @@ extends Spatial
var prev_pos=null
-func _input(ev):
- if (ev.type in [InputEvent.MOUSE_BUTTON,InputEvent.MOUSE_MOTION]):
- var pos = ev.pos
- var rfrom = get_node("camera").project_ray_origin(pos)
- var rnorm = get_node("camera").project_ray_normal(pos)
+
+func _input( ev ):
+ #all other (non-mouse) events
+ if (not ev.type in [InputEvent.MOUSE_BUTTON,InputEvent.MOUSE_MOTION,InputEvent.SCREEN_DRAG,InputEvent.SCREEN_TOUCH]):
+ get_node("viewport").input(ev)
- #simple collision test against aligned plane
- #for game UIs of this kind consider more complex collision against plane
- var p = Plane(Vector3(0,0,1),0).intersects_ray(rfrom,rnorm)
- if (p==null):
- return
-
- pos.x=(p.x+1.5)*100
- pos.y=(-p.y+0.75)*100
- ev.pos=pos
- ev.global_pos=pos
- if (prev_pos==null):
- prev_pos=pos
- if (ev.type==InputEvent.MOUSE_MOTION):
- ev.relative_pos=pos-prev_pos
+
+#mouse events for area
+func _on_area_input_event( camera, ev, click_pos, click_normal, shape_idx ):
+
+ #use click pos (click in 3d space, convert to area space
+ var pos = get_node("area").get_global_transform().affine_inverse() * click_pos
+ #convert to 2D
+ pos = Vector2(pos.x,pos.y)
+ #convert to viewport coordinate system
+ pos.x=(pos.x+1.5)*100
+ pos.y=(-pos.y+0.75)*100
+ #set to event
+ ev.pos=pos
+ ev.global_pos=pos
+ if (prev_pos==null):
prev_pos=pos
+ if (ev.type==InputEvent.MOUSE_MOTION):
+ ev.relative_pos=pos-prev_pos
+ prev_pos=pos
get_node("viewport").input(ev)
-
-
+
func _ready():
# Initalization here
- get_node("quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE, get_node("viewport").get_render_target_texture() )
+ get_node("area/quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE, get_node("viewport").get_render_target_texture() )
set_process_input(true)
-
pass
-
diff --git a/demos/viewport/gui_in_3d/gui_3d.scn b/demos/viewport/gui_in_3d/gui_3d.scn
index df8f7d6dc5..c69d4dc73f 100644
--- a/demos/viewport/gui_in_3d/gui_3d.scn
+++ b/demos/viewport/gui_in_3d/gui_3d.scn
Binary files differ
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 35de0106b5..342941970f 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -257,13 +257,14 @@
<method name="lerp" >
<return type="float">
</return>
- <argument index="0" name="a" type="float">
+ <argument index="0" name="from" type="float">
</argument>
- <argument index="1" name="b" type="float">
+ <argument index="1" name="to" type="float">
</argument>
- <argument index="2" name="c" type="float">
+ <argument index="2" name="weight" type="float">
</argument>
<description>
+ Linear interpolates between two values by a normalized value.
</description>
</method>
<method name="dectime" >
@@ -276,6 +277,7 @@
<argument index="2" name="step" type="float">
</argument>
<description>
+ Decreases time by a specified amount.
</description>
</method>
<method name="randomize" >
@@ -421,6 +423,7 @@
<argument index="1" name="funcname" type="String">
</argument>
<description>
+ Returns a reference to the specified function
</description>
</method>
<method name="convert" >
@@ -475,6 +478,7 @@
<argument index="1" name="..." type="var">
</argument>
<description>
+ Print one or more arguments to the console with a tab between each argument.
</description>
</method>
<method name="printerr" >
@@ -499,6 +503,24 @@
Print one or more arguments to strings in the best way possible to console. No newline is added at the end.
</description>
</method>
+ <method name="var2str" >
+ <return type="String">
+ </return>
+ <argument index="0" name="var" type="var">
+ </argument>
+ <description>
+ Converts the value of a variable to a String.
+ </description>
+ </method>
+ <method name="str2var:var" >
+ <return type="String">
+ </return>
+ <argument index="0" name="str" type="String">
+ </argument>
+ <description>
+ Converts the value of a String to a variable.
+ </description>
+ </method>
<method name="range" >
<return type="Array">
</return>
@@ -544,6 +566,7 @@
<argument index="0" name="var:var" type="var">
</argument>
<description>
+ Hashes the variable passed and returns an integer.
</description>
</method>
<method name="print_stack" >
@@ -18902,7 +18925,8 @@
collider_id: collider id of the object agaisnt which the ray was stopped[br]
collider: collider object agaisnt which the ray was stopped[br]
rid: [RID] of the object agaisnt which the ray was stopped[br]
- If the ray did not intersect anything, then null is returned instead of a [Dictionary].
+ If the ray did not intersect anything, then an empty
+ dictionary (dir.empty()==true) is returned instead.
</description>
</method>
<method name="intersect_shape" >
diff --git a/drivers/SCsub b/drivers/SCsub
index 46334468ba..a1a2191cbc 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -10,7 +10,6 @@ SConscript('alsa/SCsub');
SConscript('pulseaudio/SCsub');
SConscript('windows/SCsub');
SConscript('gles2/SCsub');
-SConscript('gles1/SCsub');
SConscript('gl_context/SCsub');
SConscript('openssl/SCsub');
diff --git a/drivers/etc1/rg_etc1.cpp b/drivers/etc1/rg_etc1.cpp
index cad9af8830..63877e6d12 100644
--- a/drivers/etc1/rg_etc1.cpp
+++ b/drivers/etc1/rg_etc1.cpp
@@ -2367,7 +2367,7 @@ found_perfect_match:
int dr = best_results[1].m_block_color_unscaled.r - best_results[0].m_block_color_unscaled.r;
int dg = best_results[1].m_block_color_unscaled.g - best_results[0].m_block_color_unscaled.g;
int db = best_results[1].m_block_color_unscaled.b - best_results[0].m_block_color_unscaled.b;
- RG_ETC1_ASSERT(best_use_color4 || (rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax));
+ RG_ETC1_ASSERT(best_use_color4 || ((rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax)));
if (best_use_color4)
{
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index fe42b67d23..05c977f344 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -971,7 +971,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
- if ((!texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) {
+ if (!(texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) {
texture->has_alpha=true;
}
@@ -989,8 +989,14 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps)
glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR);
- else
- glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ else {
+ if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
+ glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ } else {
+ glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ }
+ }
if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
@@ -1283,8 +1289,14 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) {
if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps)
glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR);
- else
- glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ else{
+ if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
+ glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ } else {
+ glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ }
+ }
if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
@@ -2525,7 +2537,7 @@ Error RasterizerGLES2::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem,ui
void RasterizerGLES2::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) {
ERR_EXPLAIN("OpenGL Rasterizer does not support custom surfaces. Running on wrong platform?");
- ERR_FAIL_V();
+ ERR_FAIL();
}
Array RasterizerGLES2::mesh_get_surface_arrays(RID p_mesh,int p_surface) const {
@@ -4116,6 +4128,10 @@ void RasterizerGLES2::begin_frame() {
shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter")));
#endif
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF5,shadow_filter==SHADOW_FILTER_PCF5);
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF13,shadow_filter==SHADOW_FILTER_PCF13);
+ canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM);
+
window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height );
double time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec
@@ -4272,7 +4288,7 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) {
void RasterizerGLES2::clear_viewport(const Color& p_color) {
- if (current_rt) {
+ if (current_rt || using_canvas_bg) {
glScissor( 0, 0, viewport.width, viewport.height );
} else {
@@ -4280,7 +4296,7 @@ void RasterizerGLES2::clear_viewport(const Color& p_color) {
}
glEnable(GL_SCISSOR_TEST);
- glClearColor(p_color.r,p_color.g,p_color.b,1.0);
+ glClearColor(p_color.r,p_color.g,p_color.b,p_color.a);
glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared..
glDisable(GL_SCISSOR_TEST);
};
@@ -6398,7 +6414,12 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
case VS::MATERIAL_BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
} break;
case VS::MATERIAL_BLEND_MODE_ADD: {
@@ -6414,7 +6435,12 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
} break;
case VS::MATERIAL_BLEND_MODE_MUL: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
} break;
@@ -6681,7 +6707,12 @@ void RasterizerGLES2::_copy_to_texscreen() {
#endif
glDisable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
//glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
@@ -6913,7 +6944,7 @@ void RasterizerGLES2::_draw_tex_bg() {
RID texture;
- if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+ if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
texture=current_env->bg_param[VS::ENV_BG_PARAM_TEXTURE];
} else {
texture=current_env->bg_param[VS::ENV_BG_PARAM_CUBEMAP];
@@ -6930,25 +6961,20 @@ void RasterizerGLES2::_draw_tex_bg() {
copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY,true);
- if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+ if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,false);
} else {
copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,true);
}
- if (current_env->bg_mode==VS::ENV_BG_CUBEMAP_RGBE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
- copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,true);
- } else {
- copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false);
- }
copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true);
copy_shader.bind();
- if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+ if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
} else {
glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE_CUBE),0);
@@ -6975,7 +7001,7 @@ void RasterizerGLES2::_draw_tex_bg() {
Vector3( 0, 0, 0)
};
- if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+ if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
//regular texture
//adjust aspect
@@ -7045,7 +7071,7 @@ void RasterizerGLES2::end_scene() {
if (framebuffer.active) {
//detect when to use the framebuffer object
- if (texscreen_used || framebuffer.scale!=1) {
+ if (using_canvas_bg || texscreen_used || framebuffer.scale!=1) {
use_fb=true;
} else if (current_env) {
use_fb=false;
@@ -7097,6 +7123,7 @@ void RasterizerGLES2::end_scene() {
switch(current_env->bg_mode) {
+ case VS::ENV_BG_CANVAS:
case VS::ENV_BG_KEEP: {
//copy from framebuffer if framebuffer
glClear(GL_DEPTH_BUFFER_BIT);
@@ -7109,7 +7136,7 @@ void RasterizerGLES2::end_scene() {
bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR];
else
bgcolor = Globals::get_singleton()->get("render/default_clear_color");
- bgcolor = _convert_color(bgcolor);
+ bgcolor = _convert_color(bgcolor);
float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0;
glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a);
_glClearDepth(1.0);
@@ -7117,9 +7144,7 @@ void RasterizerGLES2::end_scene() {
} break;
case VS::ENV_BG_TEXTURE:
- case VS::ENV_BG_CUBEMAP:
- case VS::ENV_BG_TEXTURE_RGBE:
- case VS::ENV_BG_CUBEMAP_RGBE: {
+ case VS::ENV_BG_CUBEMAP: {
glClear(GL_DEPTH_BUFFER_BIT);
@@ -7155,7 +7180,12 @@ void RasterizerGLES2::end_scene() {
current_depth_mask=true;
texscreen_copied=false;
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
glDisable(GL_BLEND);
current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
@@ -7172,7 +7202,12 @@ void RasterizerGLES2::end_scene() {
}
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
glDisable(GL_BLEND);
current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,false);
@@ -7328,8 +7363,12 @@ void RasterizerGLES2::end_scene() {
_debug_shadows();
}
// _debug_luminances();
- _debug_samplers();
+// _debug_samplers();
+ if (using_canvas_bg) {
+ using_canvas_bg=false;
+ glColorMask(1,1,1,1); //don't touch alpha
+ }
}
void RasterizerGLES2::end_shadow_map() {
@@ -7798,8 +7837,26 @@ void RasterizerGLES2::flush_frame() {
/* CANVAS API */
+void RasterizerGLES2::begin_canvas_bg() {
+
+ if (framebuffer.active) {
+ using_canvas_bg=true;
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo);
+ glViewport( 0,0,viewport.width , viewport.height );
+ } else {
+ using_canvas_bg=false;
+ }
+
+}
+
void RasterizerGLES2::canvas_begin() {
+
+ if (using_canvas_bg) {
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo);
+ glColorMask(1,1,1,0); //don't touch alpha
+ }
+
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
@@ -7809,7 +7866,12 @@ void RasterizerGLES2::canvas_begin() {
#endif
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
//glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glLineWidth(1.0);
glBindBuffer(GL_ARRAY_BUFFER,0);
@@ -7844,7 +7906,8 @@ void RasterizerGLES2::canvas_begin() {
canvas_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
canvas_texscreen_used=false;
uses_texpixel_size=false;
- canvas_last_shader=RID();
+
+ canvas_last_material=NULL;
}
@@ -7866,7 +7929,12 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) {
case VS::MATERIAL_BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
} break;
case VS::MATERIAL_BLEND_MODE_ADD: {
@@ -8329,6 +8397,476 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) {
//canvas_transform = Variant(p_transform);
}
+RID RasterizerGLES2::canvas_light_occluder_create() {
+
+ CanvasOccluder *co = memnew( CanvasOccluder );
+ co->index_id=0;
+ co->vertex_id=0;
+ co->len=0;
+
+ return canvas_occluder_owner.make_rid(co);
+}
+
+void RasterizerGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) {
+
+ CanvasOccluder *co = canvas_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!co);
+
+ co->lines=p_lines;
+
+ if (p_lines.size()!=co->len) {
+
+ if (co->index_id)
+ glDeleteBuffers(1,&co->index_id);
+ if (co->vertex_id)
+ glDeleteBuffers(1,&co->vertex_id);
+
+ co->index_id=0;
+ co->vertex_id=0;
+ co->len=0;
+
+ }
+
+ if (p_lines.size()) {
+
+
+
+ DVector<float> geometry;
+ DVector<uint16_t> indices;
+ int lc = p_lines.size();
+
+ geometry.resize(lc*6);
+ indices.resize(lc*3);
+
+ DVector<float>::Write vw=geometry.write();
+ DVector<uint16_t>::Write iw=indices.write();
+
+
+ DVector<Vector2>::Read lr=p_lines.read();
+
+ const int POLY_HEIGHT = 16384;
+
+ for(int i=0;i<lc/2;i++) {
+
+ vw[i*12+0]=lr[i*2+0].x;
+ vw[i*12+1]=lr[i*2+0].y;
+ vw[i*12+2]=POLY_HEIGHT;
+
+ vw[i*12+3]=lr[i*2+1].x;
+ vw[i*12+4]=lr[i*2+1].y;
+ vw[i*12+5]=POLY_HEIGHT;
+
+ vw[i*12+6]=lr[i*2+1].x;
+ vw[i*12+7]=lr[i*2+1].y;
+ vw[i*12+8]=-POLY_HEIGHT;
+
+ vw[i*12+9]=lr[i*2+0].x;
+ vw[i*12+10]=lr[i*2+0].y;
+ vw[i*12+11]=-POLY_HEIGHT;
+
+ iw[i*6+0]=i*4+0;
+ iw[i*6+1]=i*4+1;
+ iw[i*6+2]=i*4+2;
+
+ iw[i*6+3]=i*4+2;
+ iw[i*6+4]=i*4+3;
+ iw[i*6+5]=i*4+0;
+
+ }
+
+ //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
+
+
+ if (!co->vertex_id) {
+ glGenBuffers(1,&co->vertex_id);
+ glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id);
+ glBufferData(GL_ARRAY_BUFFER,lc*6*sizeof(real_t),vw.ptr(),GL_STATIC_DRAW);
+ } else {
+
+ glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id);
+ glBufferSubData(GL_ARRAY_BUFFER,0,lc*6*sizeof(real_t),vw.ptr());
+
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
+
+ if (!co->index_id) {
+
+ glGenBuffers(1,&co->index_id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,lc*3*sizeof(uint16_t),iw.ptr(),GL_STATIC_DRAW);
+ } else {
+
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,lc*3*sizeof(uint16_t),iw.ptr());
+ }
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind
+
+ co->len=lc;
+
+ }
+
+
+
+}
+
+RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
+
+ CanvasLightShadow *cls = memnew( CanvasLightShadow );
+ if (p_width>max_texture_size)
+ p_width=max_texture_size;
+
+ cls->size=p_width;
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenFramebuffers(1, &cls->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ // Create a render buffer
+ glGenRenderbuffers(1, &cls->rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, cls->rbo);
+
+ // Create a texture for storing the depth
+ glGenTextures(1, &cls->depth);
+ glBindTexture(GL_TEXTURE_2D, cls->depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // Remove artifact on the edges of the shadowmap
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ cls->height=16;
+
+ //print_line("ERROR? "+itos(glGetError()));
+ if ( read_depth_supported ) {
+
+ // We'll use a depth texture to store the depths in the shadow map
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cls->size, cls->height, 0,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+#ifdef GLEW_ENABLED
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+ // Attach the depth texture to FBO depth attachment point
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, cls->depth, 0);
+
+#ifdef GLEW_ENABLED
+ glDrawBuffer(GL_NONE);
+#endif
+ } else {
+ // We'll use a RGBA texture into which we pack the depth info
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ // Attach the RGBA texture to FBO color attachment point
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, cls->depth, 0);
+
+ // Allocate 16-bit depth buffer
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
+
+ // Attach the render buffer as depth buffer - will be ignored
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, cls->rbo);
+
+
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ //printf("errnum: %x\n",status);
+#ifdef GLEW_ENABLED
+ if (read_depth_supported) {
+ //glDrawBuffer(GL_BACK);
+ }
+#endif
+ glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
+ DEBUG_TEST_ERROR("2D Shadow Buffer Init");
+ ERR_FAIL_COND_V( status != GL_FRAMEBUFFER_COMPLETE, RID() );
+
+#ifdef GLEW_ENABLED
+ if (read_depth_supported) {
+ //glDrawBuffer(GL_BACK);
+ }
+#endif
+
+ return canvas_light_shadow_owner.make_rid(cls);
+}
+
+void RasterizerGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) {
+
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_buffer);
+ ERR_FAIL_COND(!cls);
+
+
+ glDisable(GL_BLEND);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DITHER);
+ glDisable(GL_CULL_FACE);
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(true);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ if (!use_rgba_shadowmaps)
+ glColorMask(0, 0, 0, 0);
+
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ canvas_shadow_shader.bind();
+
+ const int vp_height = 10;
+
+ glViewport(0, 0, cls->size,cls->height);
+ _glClearDepth(1.0f);
+ glClearColor(1,1,1,1);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ VS::CanvasOccluderPolygonCullMode cull=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
+
+
+ for(int i=0;i<4;i++) {
+
+ //make sure it remains orthogonal, makes easy to read angle later
+
+ Transform light;
+ light.origin[0]=p_light_xform[2][0];
+ light.origin[1]=p_light_xform[2][1];
+ light.basis[0][0]=p_light_xform[0][0];
+ light.basis[0][1]=p_light_xform[1][0];
+ light.basis[1][0]=p_light_xform[0][1];
+ light.basis[1][1]=p_light_xform[1][1];
+
+ //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
+
+ /// p_near=1;
+ CameraMatrix projection;
+ {
+ real_t fov = 90;
+ real_t near = p_near;
+ real_t far = p_far;
+ real_t aspect = 1.0;
+
+ real_t ymax = near * Math::tan( Math::deg2rad( fov * 0.5 ) );
+ real_t ymin = - ymax;
+ real_t xmin = ymin * aspect;
+ real_t xmax = ymax * aspect;
+
+ projection.set_frustum( xmin, xmax, ymin, ymax, near, far );
+ }
+
+ Vector3 cam_target=Matrix3(Vector3(0,0,Math_PI*2*(i/4.0))).xform(Vector3(0,1,0));
+ projection = projection * CameraMatrix(Transform().looking_at(cam_target,Vector3(0,0,-1)).affine_inverse());
+
+ //print_line("near: "+rtos(p_near));
+ //print_line("far: "+rtos(p_far));
+ //projection.set_perspective(60,size/float(vp_height),p_near,p_far);
+
+ // CameraMatrix light_mat = projection * CameraMatrix(camera);
+
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX,projection);
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX,light);
+
+ if (i==0)
+ *p_xform_cache=projection;
+
+ glViewport(0, (cls->height/4)*i, cls->size,cls->height/4);
+
+ CanvasLightOccluderInstance *instance=p_occluders;
+
+ while(instance) {
+
+ CanvasOccluder *cc = canvas_occluder_owner.get(instance->polygon_buffer);
+ if (!cc || cc->len==0 || !(p_light_mask&instance->light_mask)) {
+
+ instance=instance->next;
+ continue;
+ }
+
+ canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX,instance->xform_cache);
+ if (cull!=instance->cull_cache) {
+
+ cull=instance->cull_cache;
+ switch(cull) {
+ case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: {
+
+ glDisable(GL_CULL_FACE);
+
+ } break;
+ case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: {
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ } break;
+ case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: {
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
+ } break;
+ }
+ }
+/*
+ if (i==0) {
+ for(int i=0;i<cc->lines.size();i++) {
+ Vector2 p = instance->xform_cache.xform(cc->lines.get(i));
+ Plane pp(Vector3(p.x,p.y,0),1);
+ pp.normal = light.xform(pp.normal);
+ pp = projection.xform4(pp);
+ print_line(itos(i)+": "+pp.normal/pp.d);
+ //pp=light_mat.xform4(pp);
+ //print_line(itos(i)+": "+pp.normal/pp.d);
+ }
+ }
+*/
+ glBindBuffer(GL_ARRAY_BUFFER,cc->vertex_id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,cc->index_id);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0);
+ glDrawElements(GL_TRIANGLES,cc->len*3,GL_UNSIGNED_SHORT,0);
+
+
+ instance=instance->next;
+ }
+
+
+ }
+
+ glDisableVertexAttribArray(VS::ARRAY_VERTEX);
+ glBindBuffer(GL_ARRAY_BUFFER,0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+
+ if (shadow_filter==SHADOW_FILTER_ESM) {
+ //blur the buffer
+#if 0
+ //this is ignord, it did not make any difference..
+ if (read_depth_supported) {
+ glDepthFunc(GL_ALWAYS);
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(false);
+ }
+ glDisable(GL_CULL_FACE);
+ glViewport(0, 0, cls->size,cls->height);
+
+ int passes=1;
+ CanvasLightShadow *blur = canvas_light_shadow_owner.get(canvas_shadow_blur);
+
+ copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,true);
+ copy_shader.bind();
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,1);
+ copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1);
+ glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
+
+ for(int i=0;i<passes;i++) {
+
+ glBindFramebuffer(GL_FRAMEBUFFER, blur->fbo);
+ glActiveTexture(GL_TEXTURE0);
+
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,cls->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,cls->rgba);
+
+
+ {
+ Vector2 src_sb_uv[4]={
+ Vector2( 0, 1),
+ Vector2( 1, 1),
+ Vector2( 1, 0),
+ Vector2( 0, 0)
+ };
+ static const Vector2 dst_pos[4]={
+ Vector2(-1, 1),
+ Vector2( 1, 1),
+ Vector2( 1,-1),
+ Vector2(-1,-1)
+ };
+
+
+
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/cls->size);
+ _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,blur->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,blur->rgba);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ {
+ float hlimit = float(cls->size) / blur->size;
+ //hlimit*=2.0;
+ Vector2 src_sb_uv[4]={
+ Vector2( 0, 1),
+ Vector2( hlimit, 1),
+ Vector2( hlimit, 0),
+ Vector2( 0, 0)
+ };
+ static const Vector2 dst_pos[4]={
+ Vector2(-1, 1),
+ Vector2( 1, 1),
+ Vector2( 1,-1),
+ Vector2(-1,-1)
+ };
+
+
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/blur->size);
+ _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv);
+ }
+
+ }
+ copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false);
+ glDepthFunc(GL_LEQUAL);
+#endif
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
+ glColorMask(1, 1, 1, 1);
+
+
+
+}
+
+
+void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) {
+
+ CanvasLight* light=p_lights_with_shadow;
+
+ canvas_begin(); //reset
+
+ int h = 10;
+ int w = viewport.width;
+ int ofs = h;
+ while(light) {
+
+ if (light->shadow_buffer.is_valid()) {
+
+ CanvasLightShadow * sb = canvas_light_shadow_owner.get(light->shadow_buffer);
+ if (sb) {
+ glActiveTexture(GL_TEXTURE0);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,sb->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,sb->rgba);
+ _draw_textured_quad(Rect2(h,ofs,w-h*2,h),Rect2(0,0,sb->size,10),Size2(sb->size,10),false,false);
+ ofs+=h*2;
+
+ }
+ }
+
+ light=light->shadows_next_ptr;
+ }
+
+}
+
void RasterizerGLES2::_canvas_normal_set_flip(const Vector2& p_flip) {
if (p_flip==normal_flip)
@@ -8473,14 +9011,14 @@ void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem
}
-void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItem *shader_owner,Shader* shader) {
+void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* shader) {
if (canvas_shader.bind())
rebind_texpixel_size=true;
- if (shader_owner->shader_version!=shader->version) {
+ if (material->shader_version!=shader->version) {
//todo optimize uniforms
- shader_owner->shader_version=shader->version;
+ material->shader_version=shader->version;
}
if (shader->has_texscreen && framebuffer.active) {
@@ -8513,24 +9051,19 @@ void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItem *shader_owner,
canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height));
}
- if (shader->uses_time) {
- canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0));
- draw_next_frame=true;
- }
- //if uses TIME - draw_next_frame=true
uses_texpixel_size=shader->uses_texpixel_size;
}
-void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* shader) {
+void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* shader) {
//this can be optimized..
int tex_id=1;
int idx=0;
for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
- Map<StringName,Variant>::Element *F=shader_owner->shader_param.find(E->key());
+ Map<StringName,Variant>::Element *F=material->shader_param.find(E->key());
if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
@@ -8573,6 +9106,13 @@ void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItem *shader_owne
glActiveTexture(GL_TEXTURE0);
}
+ if (shader->uses_time) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0));
+ draw_next_frame=true;
+ }
+ //if uses TIME - draw_next_frame=true
+
+
}
void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) {
@@ -8587,6 +9127,10 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_use_modulate=p_modulate!=Color(1,1,1,1);
canvas_modulate=p_modulate;
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false);
+
+ bool reset_modulate=false;
+ bool prev_distance_field=false;
while(p_item_list) {
@@ -8597,16 +9141,27 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
}
memdelete(ci->vp_render);
- ci->vp_render=NULL;
- canvas_last_shader=RID();
+ ci->vp_render=NULL;
+ canvas_last_material=NULL;
canvas_use_modulate=p_modulate!=Color(1,1,1,1);
canvas_modulate=p_modulate;
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false);
+ prev_distance_field=false;
rebind_shader=true;
+ reset_modulate=true;
+
+ }
+
+ if (prev_distance_field!=ci->distance_field) {
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,ci->distance_field);
+ prev_distance_field=ci->distance_field;
+ rebind_shader=true;
}
+
if (current_clip!=ci->final_clip_owner) {
current_clip=ci->final_clip_owner;
@@ -8623,15 +9178,50 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
}
}
+ if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) {
+
+ Rect2 rect;
+ int x,y,w,h;
+
+ if (ci->copy_back_buffer->full) {
+
+ x = viewport.x;
+ y = window_size.height-(viewport.height+viewport.y);
+ w = viewport.width;
+ h = viewport.height;
+ } else {
+ x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x;
+ y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y);
+ w = ci->copy_back_buffer->screen_rect.size.x;
+ h = ci->copy_back_buffer->screen_rect.size.y;
+ }
+ glActiveTexture(GL_TEXTURE0+max_texture_units-1);
+ glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color);
+
+#ifdef GLEW_ENABLED
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+#endif
+ glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,w,h);
+// if (current_clip) {
+// // print_line(" a clip ");
+// }
+
+ canvas_texscreen_used=true;
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+
+
//begin rect
- CanvasItem *shader_owner = ci->shader_owner?ci->shader_owner:ci;
+ CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci;
+ CanvasItemMaterial *material = material_owner->material;
- if (shader_owner->shader!=canvas_last_shader || rebind_shader) {
+ if (material!=canvas_last_material || rebind_shader) {
Shader *shader = NULL;
- if (shader_owner->shader.is_valid()) {
- shader = this->shader_owner.get(shader_owner->shader);
+ if (material && material->shader.is_valid()) {
+ shader = shader_owner.get(material->shader);
if (shader && !shader->valid) {
shader=NULL;
}
@@ -8641,7 +9231,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
if (shader) {
canvas_shader.set_custom_shader(shader->custom_code_id);
- _canvas_item_setup_shader_params(shader_owner,shader);
+ _canvas_item_setup_shader_params(material,shader);
} else {
shader_cache=NULL;
canvas_shader.set_custom_shader(0);
@@ -8653,16 +9243,26 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
if (canvas_use_modulate)
- canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
- canvas_last_shader=shader_owner->shader;
+ reset_modulate=true;
+ canvas_last_material=material;
rebind_shader=false;
}
- if (shader_cache) {
+ if (material && shader_cache) {
+
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
+ }
- _canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
+ if (material && material->unshaded) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1));
+ reset_modulate=true;
+ } else if (reset_modulate) {
+ canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
+ reset_modulate=false;
}
+
+
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
@@ -8675,7 +9275,12 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
case VS::MATERIAL_BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
} break;
case VS::MATERIAL_BLEND_MODE_ADD: {
@@ -8707,7 +9312,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
_canvas_item_render_commands<false>(ci,current_clip,reclip);
- if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light) {
+ if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && (!material || !material->unshaded)) {
CanvasLight *light = p_light;
bool light_used=false;
@@ -8745,13 +9350,18 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
normal_flip=Vector2(1,1);
}
+
+ bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask&light->item_shadow_mask;
+
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,has_shadow);
+
bool light_rebind = canvas_shader.bind();
if (light_rebind) {
- if (shader_owner && shader_cache) {
- _canvas_item_setup_shader_params(shader_owner,shader_cache);
- _canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
+ if (material && shader_cache) {
+ _canvas_item_setup_shader_params(material,shader_cache);
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
}
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
@@ -8760,6 +9370,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
if (canvas_use_modulate)
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,Vector2(1,1));
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE,1.0/light->shadow_buffer_size);
}
@@ -8768,6 +9379,24 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
+
+ if (has_shadow) {
+
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get(light->shadow_buffer);
+ glActiveTexture(GL_TEXTURE0+max_texture_units-3);
+ if (read_depth_supported)
+ glBindTexture(GL_TEXTURE_2D,cls->depth);
+ else
+ glBindTexture(GL_TEXTURE_2D,cls->rgba);
+
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3);
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache);
+ canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult);
+
+ }
+
+
glActiveTexture(GL_TEXTURE0+max_texture_units-2);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2);
Texture *t = texture_owner.get(light->texture);
@@ -8791,12 +9420,13 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,false);
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,false);
canvas_shader.bind();
- if (shader_owner && shader_cache) {
- _canvas_item_setup_shader_params(shader_owner,shader_cache);
- _canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
+ if (material && shader_cache) {
+ _canvas_item_setup_shader_params(material,shader_cache);
+ _canvas_item_setup_shader_uniforms(material,shader_cache);
}
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
@@ -8805,7 +9435,12 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ if (current_rt && current_rt_transparent) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
}
@@ -9022,6 +9657,11 @@ bool RasterizerGLES2::is_environment(const RID& p_rid) const {
}
bool RasterizerGLES2::is_shader(const RID& p_rid) const {
+ return shader_owner.owns(p_rid);
+}
+
+bool RasterizerGLES2::is_canvas_light_occluder(const RID& p_rid) const {
+
return false;
}
@@ -9199,7 +9839,30 @@ void RasterizerGLES2::free(const RID& p_rid) {
glDeleteTextures(1,&sampled_light->texture);
sampled_light_owner.free(p_rid);
memdelete( sampled_light );
+ } else if (canvas_occluder_owner.owns(p_rid)) {
+
+
+ CanvasOccluder *co = canvas_occluder_owner.get(p_rid);
+ if (co->index_id)
+ glDeleteBuffers(1,&co->index_id);
+ if (co->vertex_id)
+ glDeleteBuffers(1,&co->vertex_id);
+
+ canvas_occluder_owner.free(p_rid);
+ memdelete(co);
+
+ } else if (canvas_light_shadow_owner.owns(p_rid)) {
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid);
+ glDeleteFramebuffers(1,&cls->fbo);
+ glDeleteRenderbuffers(1,&cls->rbo);
+ glDeleteTextures(1,&cls->depth);
+ if (!read_depth_supported) {
+ glDeleteTextures(1,&cls->rgba);
+ }
+
+ canvas_light_shadow_owner.free(p_rid);
+ memdelete(cls);
};
}
@@ -9315,7 +9978,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) {
//printf("errnum: %x\n",status);
#ifdef GLEW_ENABLED
if (p_use_depth) {
- glDrawBuffer(GL_BACK);
+ //glDrawBuffer(GL_BACK);
}
#endif
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -9324,7 +9987,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) {
#ifdef GLEW_ENABLED
if (p_use_depth) {
- glDrawBuffer(GL_BACK);
+ //glDrawBuffer(GL_BACK);
}
#endif
@@ -9734,10 +10397,12 @@ void RasterizerGLES2::init() {
material_shader.init();
canvas_shader.init();
copy_shader.init();
+ canvas_shadow_shader.init();
#ifdef GLEW_ENABLED
material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL,true);
canvas_shader.set_conditional(CanvasShaderGLES2::USE_GLES_OVER_GL,true);
+ canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_GLES_OVER_GL,true);
copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL,true);
#endif
@@ -9878,8 +10543,11 @@ void RasterizerGLES2::init() {
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_texture_size);
//read_depth_supported=false;
+ canvas_shadow_blur = canvas_light_shadow_buffer_create(max_texture_size);
+
{
//shadowmaps
OS::VideoMode vm=OS::get_singleton()->get_video_mode();
@@ -9901,6 +10569,7 @@ void RasterizerGLES2::init() {
//material_shader
material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
+ canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
}
@@ -9926,14 +10595,14 @@ void RasterizerGLES2::init() {
glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
-
+ using_canvas_bg=false;
_update_framebuffer();
DEBUG_TEST_ERROR("Initializing");
}
void RasterizerGLES2::finish() {
-
+ free(canvas_shadow_blur);
}
int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) {
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index 173ca14180..b7895ad82e 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -51,6 +51,7 @@
#include "drivers/gles2/shaders/material.glsl.h"
#include "drivers/gles2/shaders/canvas.glsl.h"
+#include "drivers/gles2/shaders/canvas_shadow.glsl.h"
#include "drivers/gles2/shaders/blur.glsl.h"
#include "drivers/gles2/shaders/copy.glsl.h"
#include "drivers/gles2/shader_compiler_gles2.h"
@@ -676,6 +677,7 @@ class RasterizerGLES2 : public Rasterizer {
bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0;
bg_param[VS::ENV_BG_PARAM_SCALE]=1.0;
bg_param[VS::ENV_BG_PARAM_GLOW]=0.0;
+ bg_param[VS::ENV_BG_PARAM_CANVAS_MAX_LAYER]=0;
for(int i=0;i<VS::ENV_FX_MAX;i++)
fx_enabled[i]=false;
@@ -816,6 +818,7 @@ class RasterizerGLES2 : public Rasterizer {
bool current_depth_mask;
VS::MaterialBlendMode current_blend_mode;
bool use_fast_texture_filter;
+ int max_texture_size;
bool fragment_lighting;
RID shadow_material;
@@ -1160,6 +1163,7 @@ class RasterizerGLES2 : public Rasterizer {
void _process_glow_and_bloom();
//void _update_blur_buffer();
+
/*********/
/* FRAME */
/*********/
@@ -1178,6 +1182,45 @@ class RasterizerGLES2 : public Rasterizer {
} _rinfo;
+ /*******************/
+ /* CANVAS OCCLUDER */
+ /*******************/
+
+
+ struct CanvasOccluder {
+
+ GLuint vertex_id; // 0 means, unconfigured
+ GLuint index_id; // 0 means, unconfigured
+ DVector<Vector2> lines;
+ int len;
+ };
+
+ RID_Owner<CanvasOccluder> canvas_occluder_owner;
+
+ /***********************/
+ /* CANVAS LIGHT SHADOW */
+ /***********************/
+
+
+ struct CanvasLightShadow {
+
+ int size;
+ int height;
+ GLuint fbo;
+ GLuint rbo;
+ GLuint depth;
+ GLuint rgba; //for older devices
+
+ GLuint blur;
+
+ };
+
+ RID_Owner<CanvasLightShadow> canvas_light_shadow_owner;
+
+ RID canvas_shadow_blur;
+
+ /* ETC */
+
RenderTarget *current_rt;
bool current_rt_transparent;
bool current_rt_vflip;
@@ -1192,7 +1235,7 @@ class RasterizerGLES2 : public Rasterizer {
bool uses_texpixel_size;
bool rebind_texpixel_size;
Transform canvas_transform;
- RID canvas_last_shader;
+ CanvasItemMaterial *canvas_last_material;
bool canvas_texscreen_used;
Vector2 normal_flip;
_FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip);
@@ -1216,6 +1259,7 @@ class RasterizerGLES2 : public Rasterizer {
void _process_hdr();
void _draw_tex_bg();
+ bool using_canvas_bg;
Size2 window_size;
VS::ViewportRect viewport;
double last_time;
@@ -1227,10 +1271,12 @@ class RasterizerGLES2 : public Rasterizer {
VS::ScenarioDebugMode current_debug;
RID overdraw_material;
+
mutable MaterialShaderGLES2 material_shader;
mutable CanvasShaderGLES2 canvas_shader;
BlurShaderGLES2 blur_shader;
CopyShaderGLES2 copy_shader;
+ mutable CanvasShadowShaderGLES2 canvas_shadow_shader;
mutable ShaderCompilerGLES2 shader_precompiler;
@@ -1254,8 +1300,8 @@ class RasterizerGLES2 : public Rasterizer {
template<bool use_normalmap>
_FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip);
- _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItem *shader_owner,Shader* p_shader);
- _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* p_shader);
+ _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* p_shader);
+ _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* p_shader);
public:
/* TEXTURE API */
@@ -1556,6 +1602,8 @@ public:
/* CANVAS API */
+ virtual void begin_canvas_bg();
+
virtual void canvas_begin();
virtual void canvas_disable_blending();
@@ -1572,7 +1620,17 @@ public:
virtual void canvas_set_transform(const Matrix32& p_transform);
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light);
+ virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow);
+ /* CANVAS LIGHT SHADOW */
+
+ //buffer
+ virtual RID canvas_light_shadow_buffer_create(int p_width);
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache);
+
+ //occluder
+ virtual RID canvas_light_occluder_create();
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines);
/* ENVIRONMENT */
@@ -1611,6 +1669,8 @@ public:
virtual bool is_environment(const RID& p_rid) const;
virtual bool is_shader(const RID& p_rid) const;
+ virtual bool is_canvas_light_occluder(const RID& p_rid) const;
+
virtual void free(const RID& p_rid);
virtual void init();
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index b2052c7cbb..8d378ceec1 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -61,6 +61,7 @@ static String _typestr(SL::DataType p_type) {
case SL::TYPE_VEC2: return "vec2";
case SL::TYPE_VEC3: return "vec3";
case SL::TYPE_VEC4: return "vec4";
+ case SL::TYPE_MAT2: return "mat2";
case SL::TYPE_MAT3: return "mat3";
case SL::TYPE_MAT4: return "mat4";
case SL::TYPE_TEXTURE: return "sampler2D";
@@ -284,6 +285,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
case SL::TYPE_VEC2: { Vector2 v = cnode->value; code="vec2("+_mknum(v.x)+", "+_mknum(v.y)+")"; } break;
case SL::TYPE_VEC3: { Vector3 v = cnode->value; code="vec3("+_mknum(v.x)+", "+_mknum(v.y)+", "+_mknum(v.z)+")"; } break;
case SL::TYPE_VEC4: { Plane v = cnode->value; code="vec4("+_mknum(v.normal.x)+", "+_mknum(v.normal.y)+", "+_mknum(v.normal.z)+", "+_mknum(v.d)+")"; } break;
+ case SL::TYPE_MAT2: { Matrix32 x = cnode->value; code="mat2( vec2("+_mknum(x[0][0])+", "+_mknum(x[0][1])+"), vec2("+_mknum(x[1][0])+", "+_mknum(x[1][1])+"))"; } break;
case SL::TYPE_MAT3: { Matrix3 x = cnode->value; code="mat3( vec3("+_mknum(x.get_axis(0).x)+", "+_mknum(x.get_axis(0).y)+", "+_mknum(x.get_axis(0).z)+"), vec3("+_mknum(x.get_axis(1).x)+", "+_mknum(x.get_axis(1).y)+", "+_mknum(x.get_axis(1).z)+"), vec3("+_mknum(x.get_axis(2).x)+", "+_mknum(x.get_axis(2).y)+", "+_mknum(x.get_axis(2).z)+"))"; } break;
case SL::TYPE_MAT4: { Transform x = cnode->value; code="mat4( vec4("+_mknum(x.basis.get_axis(0).x)+", "+_mknum(x.basis.get_axis(0).y)+", "+_mknum(x.basis.get_axis(0).z)+",0.0), vec4("+_mknum(x.basis.get_axis(1).x)+", "+_mknum(x.basis.get_axis(1).y)+", "+_mknum(x.basis.get_axis(1).z)+",0.0), vec4("+_mknum(x.basis.get_axis(2).x)+", "+_mknum(x.basis.get_axis(2).y)+", "+_mknum(x.basis.get_axis(2).z)+",0.0), vec4("+_mknum(x.origin.x)+", "+_mknum(x.origin.y)+", "+_mknum(x.origin.z)+",1.0))"; } break;
default: code="<error: "+Variant::get_type_name(cnode->value.get_type())+" ("+itos(cnode->datatype)+">";
@@ -476,6 +478,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
m="[2]";
else if (mnode->name=="w")
m="[3]";
+ } else if (mnode->basetype==SL::TYPE_MAT2) {
+ if (mnode->name=="x")
+ m="[0]";
+ else if (mnode->name=="y")
+ m="[1]";
} else if (mnode->basetype==SL::TYPE_MAT3) {
if (mnode->name=="x")
@@ -657,6 +664,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
replace_table["vec2" ]= "vec2";
replace_table["vec3" ]= "vec3";
replace_table["vec4" ]= "vec4";
+ replace_table["mat2" ]= "mat2";
replace_table["mat3" ]= "mat3";
replace_table["mat4" ]= "mat4";
replace_table["texture" ]= "sampler2D";
@@ -808,12 +816,19 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
mode_replace_table[4]["POINT_COORD"]="gl_PointCoord";
mode_replace_table[4]["TIME"]="time";
- mode_replace_table[5]["SRC_COLOR"]="color";
- mode_replace_table[5]["COLOR"]="color";
+ mode_replace_table[5]["POSITION"]="gl_Position";
mode_replace_table[5]["NORMAL"]="normal";
- mode_replace_table[5]["LIGHT_DIR"]="light_dir";
- mode_replace_table[5]["LIGHT_DISTANCE"]="light_distance";
- mode_replace_table[5]["LIGHT"]="light";
+ mode_replace_table[5]["UV"]="uv_interp";
+ mode_replace_table[5]["COLOR"]="color";
+ mode_replace_table[5]["TEXTURE"]="texture";
+ mode_replace_table[5]["TEXTURE_PIXEL_SIZE"]="texpixel_size";
+ mode_replace_table[5]["VAR1"]="var1_interp";
+ mode_replace_table[5]["VAR2"]="var2_interp";
+ mode_replace_table[5]["LIGHT_VEC"]="light_vec";
+ mode_replace_table[5]["LIGHT_HEIGHT"]="light_height";
+ mode_replace_table[5]["LIGHT_COLOR"]="light";
+ mode_replace_table[5]["LIGHT"]="light_out";
+ mode_replace_table[5]["SCREEN_UV"]="screen_uv";
mode_replace_table[5]["POINT_COORD"]="gl_PointCoord";
mode_replace_table[5]["TIME"]="time";
diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub
index c665cf9036..9679223b16 100644
--- a/drivers/gles2/shaders/SCsub
+++ b/drivers/gles2/shaders/SCsub
@@ -3,6 +3,7 @@ Import('env')
if env['BUILDERS'].has_key('GLSL120GLES'):
env.GLSL120GLES('material.glsl');
env.GLSL120GLES('canvas.glsl');
+ env.GLSL120GLES('canvas_shadow.glsl');
env.GLSL120GLES('blur.glsl');
env.GLSL120GLES('copy.glsl');
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 227a8b7bdd..e6d2569977 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -26,6 +26,7 @@ uniform float time;
#ifdef USE_LIGHTING
uniform highp mat4 light_matrix;
+uniform highp mat4 light_local_matrix;
uniform vec2 light_pos;
varying vec4 light_uv_interp;
@@ -34,6 +35,10 @@ varying vec4 local_rot;
uniform vec2 normal_flip;
#endif
+#ifdef USE_SHADOWS
+highp varying vec2 pos;
+#endif
+
#endif
#if defined(ENABLE_VAR1_INTERP)
@@ -63,6 +68,8 @@ VERTEX_SHADER_CODE
outvec = modelview_matrix * outvec;
#endif
+
+
#ifdef USE_PIXEL_SNAP
outvec.xy=floor(outvec.xy+0.5);
@@ -74,7 +81,10 @@ VERTEX_SHADER_CODE
#ifdef USE_LIGHTING
light_uv_interp.xy = (light_matrix * outvec).xy;
- light_uv_interp.zw = outvec.xy-light_pos;
+ light_uv_interp.zw =(light_local_matrix * outvec).xy;
+#ifdef USE_SHADOWS
+ pos=outvec.xy;
+#endif
#if defined(NORMAL_USED)
local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy )*normal_flip.x;
@@ -154,6 +164,14 @@ varying vec4 local_rot;
uniform sampler2D shadow_texture;
uniform float shadow_attenuation;
+uniform highp mat4 shadow_matrix;
+highp varying vec2 pos;
+uniform float shadowpixel_size;
+
+#ifdef SHADOW_ESM
+uniform float shadow_esm_multiplier;
+#endif
+
#endif
#endif
@@ -170,19 +188,24 @@ void main() {
vec4 color = color_interp;
#if defined(NORMAL_USED)
- vec3 normal = vec3(0,0,1);
+ vec3 normal = vec3(0.0,0.0,1.0);
#endif
-#ifdef USE_MODULATE
+#ifdef USE_DISTANCE_FIELD
+ const float smoothing = 1.0/32.0;
+ float distance = texture2D(texture, uv_interp).a;
+ color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance);
+#else
+ color *= texture2D( texture, uv_interp );
- color*=modulate;
#endif
- color *= texture2D( texture, uv_interp );
+
#if defined(ENABLE_SCREEN_UV)
vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult;
#endif
+
{
FRAGMENT_SHADER_CODE
}
@@ -191,39 +214,37 @@ FRAGMENT_SHADER_CODE
color = vec4(vec3(enc32),1.0);
#endif
+#ifdef USE_MODULATE
+
+ color*=modulate;
+#endif
+
+
#ifdef USE_LIGHTING
+ vec2 light_vec = light_uv_interp.zw;; //for shadow and normal mapping
+
#if defined(NORMAL_USED)
normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy;
#endif
float att=1.0;
- vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
-#ifdef USE_SHADOWS
- //this might not be that great on mobile?
- float light_dist = length(light_texture.zw);
- float light_angle = atan2(light_texture.x,light_texture.z) + 1.0 * 0.5;
- float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0));
- if (light_dist>shadow_dist) {
- light*=shadow_attenuation;
- }
-//use shadows
-#endif
+ vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
{
- vec2 light_dir = normalize(light_uv_interp.zw);
- float light_distance = length(light_uv_interp.zw);
+ vec4 light_out=vec4(0.0,0.0,0.0,0.0);
LIGHT_SHADER_CODE
+ color=light_out;
}
#else
#if defined(NORMAL_USED)
- vec3 light_normal = normalize(vec3(light_uv_interp.zw,-light_height));
- light*=max(dot(-light_normal,normal),0);
+ vec3 light_normal = normalize(vec3(light_vec,-light_height));
+ light*=max(dot(-light_normal,normal),0.0);
#endif
color*=light;
@@ -233,13 +254,107 @@ LIGHT_SHADER_CODE
color.zw=vec2(0.0,1.0);
#endif
*/
+
+//light shader code
+#endif
+
if (any(lessThan(light_uv_interp.xy,vec2(0.0,0.0))) || any(greaterThanEqual(light_uv_interp.xy,vec2(1.0,1.0)))) {
color.a=0.0; //invisible
+ } else {
+
+#ifdef USE_SHADOWS
+
+ float angle_to_light = -atan(light_vec.x,light_vec.y);
+ float PI = 3.14159265358979323846264;
+ /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays
+ float ang*/
+
+ float su,sz;
+
+ float abs_angle = abs(angle_to_light);
+ vec2 point;
+ float sh;
+ if (abs_angle<45.0*PI/180.0) {
+ point = light_vec;
+ sh=0.0+(1.0/8.0);
+ } else if (abs_angle>135.0*PI/180.0) {
+ point = -light_vec;
+ sh = 0.5+(1.0/8.0);
+ } else if (angle_to_light>0.0) {
+
+ point = vec2(light_vec.y,-light_vec.x);
+ sh = 0.25+(1.0/8.0);
+ } else {
+
+ point = vec2(-light_vec.y,light_vec.x);
+ sh = 0.75+(1.0/8.0);
+
+ }
+
+
+ vec4 s = shadow_matrix * vec4(point,0.0,1.0);
+ s.xyz/=s.w;
+ su=s.x*0.5+0.5;
+ sz=s.z*0.5+0.5;
+
+ float shadow_attenuation;
+
+#ifdef SHADOW_PCF5
+
+ shadow_attenuation=0.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation/=5.0;
+
+#endif
+
+#ifdef SHADOW_PCF13
+
+ shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation/=13.0;
+
+#endif
+
+#ifdef SHADOW_ESM
+
+
+ {
+ float unnormalized = su/shadowpixel_size;
+ float fractional = fract(unnormalized);
+ unnormalized = floor(unnormalized);
+ float zc = texture2D(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh)).z;
+ float zn = texture2D(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh)).z;
+ float z = mix(zc,zn,fractional);
+ shadow_attenuation=clamp(exp(shadow_esm_multiplier* ( z - sz )),0.0,1.0);
}
-//light shader code
#endif
+#if !defined(SHADOW_PCF5) && !defined(SHADOW_PCF13) && !defined(SHADOW_ESM)
+
+ shadow_attenuation = texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
+
+#endif
+
+ color.rgb*=shadow_attenuation;
+//use shadows
+#endif
+ }
+
//use lighting
#endif
// color.rgb*=color.a;
diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl
new file mode 100644
index 0000000000..40cf321dce
--- /dev/null
+++ b/drivers/gles2/shaders/canvas_shadow.glsl
@@ -0,0 +1,62 @@
+[vertex]
+
+#ifdef USE_GLES_OVER_GL
+#define mediump
+#define highp
+#else
+precision mediump float;
+precision mediump int;
+#endif
+
+uniform highp mat4 projection_matrix;
+uniform highp mat4 light_matrix;
+uniform highp mat4 world_matrix;
+
+attribute highp vec3 vertex; // attrib:0
+
+#ifndef USE_DEPTH_SHADOWS
+
+varying vec4 position_interp;
+
+#endif
+
+
+void main() {
+
+ gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0)));
+
+#ifndef USE_DEPTH_SHADOWS
+ position_interp = gl_Position;
+#endif
+
+}
+
+[fragment]
+
+#ifdef USE_GLES_OVER_GL
+#define mediump
+#define highp
+#else
+precision mediump float;
+precision mediump int;
+#endif
+
+#ifndef USE_DEPTH_SHADOWS
+
+varying vec4 position_interp;
+
+#endif
+
+void main() {
+
+#ifdef USE_DEPTH_SHADOWS
+
+#else
+ highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias;
+ highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
+ comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
+ gl_FragColor = comp;
+#endif
+
+}
+
diff --git a/drivers/trex/trex.c b/drivers/trex/trex.c
index e63a248e9e..b3668c3a11 100644
--- a/drivers/trex/trex.c
+++ b/drivers/trex/trex.c
@@ -489,7 +489,7 @@ static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *s
return cur;
}
case OP_WB:
- if(str == exp->_bol && !isspace(*str)
+ if((str == exp->_bol && !isspace(*str))
|| (str == exp->_eol && !isspace(*(str-1)))
|| (!isspace(*str) && isspace(*(str+1)))
|| (isspace(*str) && !isspace(*(str+1))) ) {
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 452d791d96..5f51865432 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -161,6 +161,7 @@ String DirAccessUnix::get_next() {
}
+ _cishidden=(fname!="." && fname!=".." && fname.begins_with("."));
@@ -173,6 +174,11 @@ bool DirAccessUnix::current_is_dir() const {
return _cisdir;
}
+bool DirAccessUnix::current_is_hidden() const {
+
+ return _cishidden;
+}
+
void DirAccessUnix::list_dir_end() {
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 119cb5c3f4..f6089ccfe1 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -50,12 +50,14 @@ class DirAccessUnix : public DirAccess {
String current_dir;
bool _cisdir;
+ bool _cishidden;
public:
virtual bool list_dir_begin(); ///< This starts dir listing
virtual String get_next();
virtual bool current_is_dir() const;
+ virtual bool current_is_hidden() const;
virtual void list_dir_end(); ///<
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 7f85526852..2f91eee90e 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -74,7 +74,7 @@ Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) {
else if (p_mode_flags==WRITE)
mode_string="wb";
else if (p_mode_flags==READ_WRITE)
- mode_string="wb+";
+ mode_string="rb+";
else
return ERR_INVALID_PARAMETER;
diff --git a/drivers/vorbis/codebook.c b/drivers/vorbis/codebook.c
index 759d7b4254..8a928cebb9 100644
--- a/drivers/vorbis/codebook.c
+++ b/drivers/vorbis/codebook.c
@@ -248,7 +248,7 @@ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
}
/* quantized values */
- if((quantvals*s->q_quant+7>>3)>opb->storage-oggpack_bytes(opb))
+ if(((quantvals*s->q_quant+7)>>3)>opb->storage-oggpack_bytes(opb))
goto _eofout;
s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals);
for(i=0;i<quantvals;i++)
diff --git a/drivers/vorbis/floor1.c b/drivers/vorbis/floor1.c
index 9f3154a6a3..ae3dcedb1f 100644
--- a/drivers/vorbis/floor1.c
+++ b/drivers/vorbis/floor1.c
@@ -1035,7 +1035,7 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
}
}
- fit_value[i]=val+predicted&0x7fff;
+ fit_value[i]=(val+predicted)&0x7fff;
fit_value[look->loneighbor[i-2]]&=0x7fff;
fit_value[look->hineighbor[i-2]]&=0x7fff;
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index d1e9766105..4c265a1ab2 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -68,6 +68,7 @@ struct DirAccessWindowsPrivate {
bool DirAccessWindows::list_dir_begin() {
_cisdir=false;
+ _cishidden=false;
if (unicode) {
list_dir_end();
@@ -95,6 +96,8 @@ String DirAccessWindows::get_next() {
if (unicode) {
_cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+ _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
+
String name=p->fu.cFileName;
if (FindNextFileW(p->h, &p->fu) == 0) {
@@ -108,6 +111,7 @@ String DirAccessWindows::get_next() {
#ifndef WINRT_ENABLED
_cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+ _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
String name=p->f.cFileName;
@@ -128,6 +132,11 @@ bool DirAccessWindows::current_is_dir() const {
return _cisdir;
}
+bool DirAccessWindows::current_is_hidden() const {
+
+ return _cishidden;
+}
+
void DirAccessWindows::list_dir_end() {
if (p->h!=INVALID_HANDLE_VALUE) {
@@ -270,7 +279,7 @@ Error DirAccessWindows::make_dir(String p_dir) {
return OK;
};
- if (err == ERROR_ALREADY_EXISTS) {
+ if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED) {
return ERR_ALREADY_EXISTS;
};
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 36530ba9b3..906ce0d064 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -58,6 +58,7 @@ class DirAccessWindows : public DirAccess {
bool unicode;
bool _cisdir;
+ bool _cishidden;
public:
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index a6073cbb29..19a62967ea 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -28,14 +28,20 @@
/*************************************************************************/
#ifdef WINDOWS_ENABLED
+#define WINVER 0x0500
+
+#include <windows.h>
+#include "shlwapi.h"
#include "file_access_windows.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <wchar.h>
#include <tchar.h>
#include "print_string.h"
+
#ifdef _MSC_VER
#define S_ISREG(m) ((m)&_S_IFREG)
#endif
@@ -65,7 +71,7 @@ Error FileAccessWindows::_open(const String& p_filename, int p_mode_flags) {
else if (p_mode_flags==WRITE)
mode_string=L"wb";
else if (p_mode_flags==READ_WRITE)
- mode_string=L"wb+";
+ mode_string=L"rb+";
else
return ERR_INVALID_PARAMETER;
@@ -111,10 +117,20 @@ void FileAccessWindows::close() {
//unlink(save_path.utf8().get_data());
//print_line("renaming..");
- _wunlink(save_path.c_str()); //unlink if exists
- int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
+ //_wunlink(save_path.c_str()); //unlink if exists
+ //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());
+
+
+ bool rename_error;
+ if (!PathFileExistsW(save_path.c_str())) {
+ //creating new file
+ rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str())!=0;
+ } else {
+ //atomic replace for existing file
+ rename_error = !ReplaceFileW(save_path.c_str(), (save_path+".tmp").c_str(), NULL, 2|4, NULL, NULL);
+ }
save_path="";
- ERR_FAIL_COND( rename_error != 0);
+ ERR_FAIL_COND( rename_error );
}
diff --git a/methods.py b/methods.py
index da1491e3f9..9608b1b61d 100755
--- a/methods.py
+++ b/methods.py
@@ -1291,6 +1291,14 @@ def android_module_manifest(self,file):
base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
f = open(base_path,"rb")
self.android_manifest_chunk+=f.read()
+def android_module_permission(self,file):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
+ f = open(base_path,"rb")
+ self.android_permission_chunk+=f.read()
+def android_module_attribute(self,file):
+ base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
+ f = open(base_path,"rb")
+ self.android_appattributes_chunk+=f.read()
def disable_module(self):
self.disabled_modules.append(self.current_module)
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index b616d8f228..f37b2f645a 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -1101,7 +1101,7 @@ MethodInfo GDFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_LERP: {
- MethodInfo mi("lerp",PropertyInfo(Variant::REAL,"a"),PropertyInfo(Variant::REAL,"b"), PropertyInfo(Variant::REAL,"c"));
+ MethodInfo mi("lerp",PropertyInfo(Variant::REAL,"from"),PropertyInfo(Variant::REAL,"to"), PropertyInfo(Variant::REAL,"weight"));
mi.return_val.type=Variant::REAL;
return mi;
} break;
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 0aa115ffbc..06c746c4fb 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -337,9 +337,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
Variant::evaluate(op,*a,*b,*dst,valid);
if (!valid) {
- if (false && dst->get_type()==Variant::STRING) {
+ if (dst->get_type()==Variant::STRING) {
//return a string when invalid with the error
err_text=*dst;
+ err_text += " in operator '"+Variant::get_operator_name(op)+"'.";
} else {
err_text="Invalid operands '"+Variant::get_type_name(a->get_type())+"' and '"+Variant::get_type_name(b->get_type())+"' in operator '"+Variant::get_operator_name(op)+"'.";
}
@@ -2696,7 +2697,10 @@ Error ResourceFormatSaverGDScript::save(const String &p_path,const RES& p_resour
}
file->store_string(source);
-
+ if (file->get_error()!=OK && file->get_error()!=ERR_FILE_EOF) {
+ memdelete(file);
+ return ERR_CANT_CREATE;
+ }
file->close();
memdelete(file);
return OK;
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 7c344e1e90..441b274e33 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -122,7 +122,7 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
Octant &g = *octant_map[ok];
g.baked=b;
- g.bake_instance=VS::get_singleton()->instance_create();;
+ g.bake_instance=VS::get_singleton()->instance_create();;
VS::get_singleton()->instance_set_base(g.bake_instance,g.baked->get_rid());
VS::get_singleton()->instance_geometry_set_baked_light(g.bake_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID());
}
@@ -418,6 +418,7 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
Octant *g = memnew( Octant );
g->dirty=true;
g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC);
+ PhysicsServer::get_singleton()->body_attach_object_instance_ID(g->static_body,get_instance_ID());
if (is_inside_world())
PhysicsServer::get_singleton()->body_set_space(g->static_body,get_world()->get_space());
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template
index 60861db603..d31bdbfa53 100644
--- a/platform/android/AndroidManifest.xml.template
+++ b/platform/android/AndroidManifest.xml.template
@@ -10,7 +10,7 @@
android:largeScreens="true"
android:xlargeScreens="true"/>
- <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false">
+ <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false" $$ADD_APPATTRIBUTE_CHUNKS$$ >
<activity android:name="com.android.godot.Godot"
android:label="@string/godot_project_name_string"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
@@ -33,6 +33,7 @@ $$ADD_APPLICATION_CHUNKS$$
</application>
<uses-feature android:glEsVersion="0x00020000"/>
+$$ADD_PERMISSION_CHUNKS$$
<uses-permission android:name="godot.ACCESS_CHECKIN_PROPERTIES"/>
<uses-permission android:name="godot.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="godot.ACCESS_FINE_LOCATION"/>
diff --git a/platform/android/SCsub b/platform/android/SCsub
index cffec5ae95..6feeb8b365 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -56,6 +56,8 @@ pp_basein = open(abspath+"/AndroidManifest.xml.template","rb")
pp_baseout = open(abspath+"/java/AndroidManifest.xml","wb")
manifest = pp_basein.read()
manifest = manifest.replace("$$ADD_APPLICATION_CHUNKS$$",env.android_manifest_chunk)
+manifest = manifest.replace("$$ADD_PERMISSION_CHUNKS$$",env.android_permission_chunk)
+manifest = manifest.replace("$$ADD_APPATTRIBUTE_CHUNKS$$",env.android_appattributes_chunk)
pp_baseout.write( manifest )
diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp
index 857d1a4a54..4c0c095e10 100644
--- a/platform/android/audio_driver_opensl.cpp
+++ b/platform/android/audio_driver_opensl.cpp
@@ -396,6 +396,14 @@ void AudioDriverOpenSL::finish(){
void AudioDriverOpenSL::set_pause(bool p_pause) {
pause=p_pause;
+
+ if (active) {
+ if (pause) {
+ (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED);
+ } else {
+ (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
+ }
+ }
}
diff --git a/platform/android/dir_access_android.cpp b/platform/android/dir_access_android.cpp
index 60bde61fc4..80311e5a08 100644
--- a/platform/android/dir_access_android.cpp
+++ b/platform/android/dir_access_android.cpp
@@ -79,6 +79,9 @@ bool DirAccessAndroid::current_is_dir() const{
return false;
}
+bool DirAccessAndroid::current_is_hidden() const{
+ return current!="." && current!=".." && current.begins_with(".");
+}
void DirAccessAndroid::list_dir_end(){
if (aad==NULL)
diff --git a/platform/android/dir_access_android.h b/platform/android/dir_access_android.h
index a6aead6eb3..57683542fa 100644
--- a/platform/android/dir_access_android.h
+++ b/platform/android/dir_access_android.h
@@ -52,6 +52,7 @@ public:
virtual bool list_dir_begin(); ///< This starts dir listing
virtual String get_next();
virtual bool current_is_dir() const;
+ virtual bool current_is_hidden() const;
virtual void list_dir_end(); ///<
virtual int get_drive_count();
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index f32e16e7d8..fda4ca7357 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -105,6 +105,9 @@ bool DirAccessJAndroid::current_is_dir() const{
return true;
}
+bool DirAccessAndroid::current_is_hidden() const{
+ return current!="." && current!=".." && current.begins_with(".");
+}
void DirAccessJAndroid::list_dir_end(){
if (id==0)
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 0312d13644..349db08e36 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -45,9 +45,18 @@ static JavaClassWrapper *java_class_wrapper=NULL;
static OS_Android *os_android=NULL;
-jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) {
+struct jvalret {
- jvalue v;
+ jobject obj;
+ jvalue val;
+ jvalret() { obj=NULL; }
+
+
+};
+
+jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) {
+
+ jvalret v;
switch(p_type) {
@@ -59,9 +68,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jvalue val;
val.z = (bool)(*p_arg);
jobject obj = env->NewObjectA(bclass, ctor, &val);
- v.l = obj;
+ v.val.l = obj;
+ v.obj=obj;
+ env->DeleteLocalRef(bclass);
} else {
- v.z=*p_arg;
+ v.val.z=*p_arg;
+
};
} break;
case Variant::INT: {
@@ -73,10 +85,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jvalue val;
val.i = (int)(*p_arg);
jobject obj = env->NewObjectA(bclass, ctor, &val);
- v.l = obj;
+ v.val.l = obj;
+ v.obj=obj;
+ env->DeleteLocalRef(bclass);
} else {
- v.i=*p_arg;
+ v.val.i=*p_arg;
+
};
} break;
case Variant::REAL: {
@@ -88,17 +103,20 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jvalue val;
val.d = (double)(*p_arg);
jobject obj = env->NewObjectA(bclass, ctor, &val);
- v.l = obj;
+ v.val.l = obj;
+ v.obj=obj;
+ env->DeleteLocalRef(bclass);
} else {
- v.f=*p_arg;
+ v.val.f=*p_arg;
};
} break;
case Variant::STRING: {
String s = *p_arg;
jstring jStr = env->NewStringUTF(s.utf8().get_data());
- v.l=jStr;
+ v.val.l=jStr;
+ v.obj=jStr;
} break;
case Variant::STRING_ARRAY: {
@@ -107,9 +125,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
for(int j=0;j<sarray.size();j++) {
- env->SetObjectArrayElement(arr,j,env->NewStringUTF( sarray[j].utf8().get_data() ));
+ jstring str = env->NewStringUTF( sarray[j].utf8().get_data() );
+ env->SetObjectArrayElement(arr,j,str);
+ env->DeleteLocalRef(str);
}
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
@@ -124,27 +145,36 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jobjectArray jkeys = env->NewObjectArray(keys.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
for (int j=0; j<keys.size(); j++) {
- env->SetObjectArrayElement(jkeys, j, env->NewStringUTF(String(keys[j]).utf8().get_data()));
+ jstring str = env->NewStringUTF(String(keys[j]).utf8().get_data());
+ env->SetObjectArrayElement(jkeys, j, str);
+ env->DeleteLocalRef(str);
};
jmethodID set_keys = env->GetMethodID(dclass, "set_keys", "([Ljava/lang/String;)V");
jvalue val;
val.l = jkeys;
env->CallVoidMethodA(jdict, set_keys, &val);
+ env->DeleteLocalRef(jkeys);
jobjectArray jvalues = env->NewObjectArray(keys.size(), env->FindClass("java/lang/Object"), NULL);
for (int j=0; j<keys.size(); j++) {
Variant var = dict[keys[j]];
- val = _variant_to_jvalue(env, var.get_type(), &var, true);
- env->SetObjectArrayElement(jvalues, j, val.l);
+ jvalret v = _variant_to_jvalue(env, var.get_type(), &var, true);
+ env->SetObjectArrayElement(jvalues, j, v.val.l);
+ if (v.obj) {
+ env->DeleteLocalRef(v.obj);
+ }
};
jmethodID set_values = env->GetMethodID(dclass, "set_values", "([Ljava/lang/Object;)V");
val.l = jvalues;
env->CallVoidMethodA(jdict, set_values, &val);
+ env->DeleteLocalRef(jvalues);
+ env->DeleteLocalRef(dclass);
- v.l = jdict;
+ v.val.l = jdict;
+ v.obj=jdict;
} break;
case Variant::INT_ARRAY: {
@@ -153,7 +183,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jintArray arr = env->NewIntArray(array.size());
DVector<int>::Read r = array.read();
env->SetIntArrayRegion(arr,0,array.size(),r.ptr());
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
case Variant::RAW_ARRAY: {
@@ -161,7 +192,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jbyteArray arr = env->NewByteArray(array.size());
DVector<uint8_t>::Read r = array.read();
env->SetByteArrayRegion(arr,0,array.size(),reinterpret_cast<const signed char*>(r.ptr()));
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
case Variant::REAL_ARRAY: {
@@ -170,12 +202,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
jfloatArray arr = env->NewFloatArray(array.size());
DVector<float>::Read r = array.read();
env->SetFloatArrayRegion(arr,0,array.size(),r.ptr());
- v.l=arr;
+ v.val.l=arr;
+ v.obj=arr;
} break;
default: {
- v.i = 0;
+ v.val.i = 0;
} break;
}
@@ -193,8 +226,11 @@ String _get_class_name(JNIEnv * env, jclass cls, bool* array) {
jboolean isarr = env->CallBooleanMethod(cls, isArray);
(*array) = isarr ? true : false;
}
+ String name = env->GetStringUTFChars( clsName, NULL );
+ env->DeleteLocalRef(clsName);
+
+ return name;
- return env->GetStringUTFChars( clsName, NULL );
};
@@ -223,6 +259,8 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
jstring string = (jstring) env->GetObjectArrayElement(arr, i);
const char *rawString = env->GetStringUTFChars(string, 0);
sarr.push_back(String(rawString));
+ env->DeleteLocalRef(string);
+
}
return sarr;
@@ -321,30 +359,34 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
jobjectArray arr = (jobjectArray)obj;
int objCount = env->GetArrayLength(arr);
- Array varr;
+ Array varr(true);
for (int i=0; i<objCount; i++) {
jobject jobj = env->GetObjectArrayElement(arr, i);
Variant v = _jobject_to_variant(env, jobj);
varr.push_back(v);
+ env->DeleteLocalRef(jobj);
+
}
return varr;
};
- if (name == "com.android.godot.Dictionary") {
+ if (name == "java.util.HashMap" || name == "com.android.godot.Dictionary") {
- Dictionary ret;
+ Dictionary ret(true);
jclass oclass = c;
jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;");
jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys);
StringArray keys = _jobject_to_variant(env, arr);
+ env->DeleteLocalRef(arr);
jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;");
arr = (jobjectArray)env->CallObjectMethod(obj, get_values);
Array vals = _jobject_to_variant(env, arr);
+ env->DeleteLocalRef(arr);
//print_line("adding " + String::num(keys.size()) + " to Dictionary!");
for (int i=0; i<keys.size(); i++) {
@@ -352,9 +394,12 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
ret[keys[i]] = vals[i];
};
+
return ret;
};
+ env->DeleteLocalRef(c);
+
return Variant();
};
@@ -432,9 +477,13 @@ public:
JNIEnv *env = ThreadAndroid::get_env();
//print_line("argcount "+String::num(p_argcount));
+ List<jobject> to_erase;
for(int i=0;i<p_argcount;i++) {
- v[i] = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]);
+ jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]);
+ v[i] = vr.val;
+ if (vr.obj)
+ to_erase.push_back(vr.obj);
}
//print_line("calling method!!");
@@ -468,6 +517,7 @@ public:
jobject o = env->CallObjectMethodA(instance,E->get().method,v);
String str = env->GetStringUTFChars((jstring)o, NULL );
ret=str;
+ env->DeleteLocalRef(o);
} break;
case Variant::STRING_ARRAY: {
@@ -475,6 +525,7 @@ public:
ret = _jobject_to_variant(env, arr);
+ env->DeleteLocalRef(arr);
} break;
case Variant::INT_ARRAY: {
@@ -488,6 +539,7 @@ public:
env->GetIntArrayRegion(arr,0,fCount,w.ptr());
w = DVector<int>::Write();
ret=sarr;
+ env->DeleteLocalRef(arr);
} break;
case Variant::REAL_ARRAY: {
@@ -501,6 +553,7 @@ public:
env->GetFloatArrayRegion(arr,0,fCount,w.ptr());
w = DVector<float>::Write();
ret=sarr;
+ env->DeleteLocalRef(arr);
} break;
case Variant::DICTIONARY: {
@@ -508,6 +561,7 @@ public:
//print_line("call dictionary");
jobject obj = env->CallObjectMethodA(instance, E->get().method, v);
ret = _jobject_to_variant(env, obj);
+ env->DeleteLocalRef(obj);
} break;
default: {
@@ -518,6 +572,10 @@ public:
} break;
}
+ while (to_erase.size()) {
+ env->DeleteLocalRef(to_erase.front()->get());
+ to_erase.pop_front();
+ }
//print_line("success");
return ret;
@@ -872,6 +930,7 @@ static void _initialize_java_modules() {
String modules = Globals::get_singleton()->get("android/modules");
Vector<String> mods = modules.split(",",false);
+ print_line("ANDROID MODULES : " + modules);
__android_log_print(ANDROID_LOG_INFO,"godot","mod count: %i",mods.size());
if (mods.size()) {
@@ -1571,6 +1630,8 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env,
memnew_placement(&vlist[i], Variant);
vlist[i] = v;
vptr[i] = &vlist[i];
+ env->DeleteLocalRef(obj);
+
};
Variant::CallError err;
@@ -1588,13 +1649,15 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env
int count = env->GetArrayLength(params);
Variant args[VARIANT_ARG_MAX];
-// print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
+ //print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
for (int i=0; i<MIN(count,VARIANT_ARG_MAX); i++) {
jobject obj = env->GetObjectArrayElement(params, i);
if (obj)
args[i] = _jobject_to_variant(env, obj);
+ env->DeleteLocalRef(obj);
+
// print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
};
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 6f1c03b593..6b91c01dfc 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -151,7 +151,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
sample_manager = memnew( SampleManagerMallocSW );
audio_server = memnew( AudioServerSW(sample_manager) );
- audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
+ audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,true);
audio_server->init();
spatial_sound_server = memnew( SpatialSoundServerSW );
diff --git a/platform/bb10/SCsub b/platform/bb10/SCsub
index 2e8ef47005..24f2b5d242 100644
--- a/platform/bb10/SCsub
+++ b/platform/bb10/SCsub
@@ -18,13 +18,5 @@ if env['bb10_lgles_override'] == "yes":
prog = None
-if env["target"]=="release":
- prog = env_bps.Program('#platform/bb10/godot_bb10_opt', bb10_lib)
-else:
- prog = env_bps.Program('#platform/bb10/godot_bb10', bb10_lib)
-
-import os
-fname = os.path.basename(str(prog[0]))
-
-env.Command('#bin/'+fname, prog, Copy('bin/'+fname, prog[0]))
+prog = env_bps.Program('#bin/godot', bb10_lib)
diff --git a/platform/bb10/bar/bar-descriptor.xml b/platform/bb10/bar/bar-descriptor.xml
index df5d34e077..0ba70b7180 100644
--- a/platform/bb10/bar/bar-descriptor.xml
+++ b/platform/bb10/bar/bar-descriptor.xml
@@ -1,65 +1,53 @@
-<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<?xml version='1.0' encoding='utf-8' standalone='no'?>
<qnx xmlns="http://www.qnx.com/schemas/application/1.0">
-
-<!-- BlackBerry® 10 application descriptor file.
+ <!-- BlackBerry® 10 application descriptor file.
Specifies parameters for identifying, installing, and launching native applications on BlackBerry® 10 OS.
-->
-
<!-- A universally unique application identifier. Must be unique across all BlackBerry applications.
Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
<id>com.godot.game</id>
-
<!-- The name that is displayed in the BlackBerry application installer.
May have multiple values for each language. See samples or xsd schema file. Optional. -->
<name>Godot Game</name>
-
<!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade.
Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
An updated version of application must have a versionNumber value higher than the previous version. Required. -->
<versionNumber>0.0.1</versionNumber>
-
<!-- Fourth digit segment of the package version. First three segments are taken from the
<versionNumber> element. Must be an integer from 0 to 2^16-1 -->
<buildId>0</buildId>
-
<!-- Description, displayed in the BlackBerry application installer.
May have multiple values for each language. See samples or xsd schema file. Optional. -->
<description>Game made with Godot Engine</description>
-
<!-- Name of author which is used for signing. Must match the developer name of your development certificate. -->
<author>You Name or Company</author>
<authorId>authorIDherePlease</authorId>
-
<!-- Unique author ID assigned by signing authority. Required if using debug tokens. -->
<!-- <authorId>ABC1234YjsnUk235h</authorId> -->
-
<initialWindow>
<aspectRatio>landscape</aspectRatio>
<autoOrients>false</autoOrients>
<systemChrome>none</systemChrome>
<transparent>false</transparent>
</initialWindow>
-
<!-- The category where the application appears. Either core.games or core.media. -->
<category>core.games</category>
<permission>read_device_identifying_information</permission>
<permission>access_internet</permission>
- <asset path="assets">assets</asset>
+ <asset path="data.pck">data.pck</asset>
<configuration name="Device-Debug">
- <platformArchitecture>armle-v7</platformArchitecture>
- <asset path="godot_bb10.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10.qnx.armle</asset>
+ <platformArchitecture>armle-v7</platformArchitecture>
+ <asset type="Qnx/Elf" path="godot.bb10.debug.qnx.armle" entry="true">godot.bb10.debug.qnx.armle</asset>
</configuration>
<configuration name="Device-Release">
- <platformArchitecture>armle-v7</platformArchitecture>
- <asset path="godot_bb10_opt.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10_opt.qnx.armle</asset>
+ <platformArchitecture>armle-v7</platformArchitecture>
+ <asset type="Qnx/Elf" path="godot.bb10.opt.qnx.armle" entry="true">godot.bb10.opt.qnx.armle</asset>
</configuration>
<!-- The icon for the application. -->
<icon>
- <image>icon.png</image>
+ <image>icon.png</image>
</icon>
-
<!-- Ensure that shared libraries in the package are found at run-time. -->
- <env var="LD_LIBRARY_PATH" value="app/native/lib:/usr/lib/qt4/lib"/>
-
+ <env value="app/native/lib:/usr/lib/qt4/lib" var="LD_LIBRARY_PATH"/>
</qnx>
diff --git a/platform/bb10/detect.py b/platform/bb10/detect.py
index 3ddb7a4450..f134a9df19 100644
--- a/platform/bb10/detect.py
+++ b/platform/bb10/detect.py
@@ -81,8 +81,6 @@ def configure(env):
if (env["target"]=="release"):
env.Append(CCFLAGS=['-O3','-DRELEASE_BUILD'])
- env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
elif (env["target"]=="debug"):
diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp
index d40cb82cdf..7862ecd493 100644
--- a/platform/bb10/export/export.cpp
+++ b/platform/bb10/export/export.cpp
@@ -321,12 +321,29 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
//BE SUPER CAREFUL WITH THIS PLEASE!!!
//BLACKBERRY THIS IS YOUR FAULT FOR NOT MAKING A BETTER WAY!!
- if (bar_dir.ends_with("bb10_export")) {
- Error err = da->erase_contents_recursive();
- if (err!=OK) {
+ bool berr = bar_dir.ends_with("bb10_export");
+ if (berr) {
+ if (da->list_dir_begin()) {
EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir);
- ERR_FAIL_COND_V(err!=OK,err);
- }
+ ERR_FAIL_COND_V(berr,FAILED);
+ };
+
+ String f = da->get_next();
+ while (f != "") {
+
+ if (f == "." || f == "..") {
+ f = da->get_next();
+ continue;
+ };
+ Error err = da->remove(bar_dir + "/" + f);
+ if (err != OK) {
+ EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir);
+ ERR_FAIL_COND_V(err!=OK,err);
+ };
+ f = da->get_next();
+ };
+
+ da->list_dir_end();
} else {
print_line("ARE YOU CRAZY??? THIS IS A SERIOUS BUG HERE!!!");
@@ -405,52 +422,23 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
ret = unzGoToNextFile(pkg);
}
- ep.step("Finding Files..",1);
-
- Vector<StringName> files=get_dependencies(false);
-
ep.step("Adding Files..",2);
- da->change_dir(bar_dir);
- da->make_dir("assets");
- Error err = da->change_dir("assets");
- ERR_FAIL_COND_V(err,err);
-
- String asset_dir=da->get_current_dir();
- if (!asset_dir.ends_with("/"))
- asset_dir+="/";
-
- for(int i=0;i<files.size();i++) {
-
- String fname=files[i];
- Vector<uint8_t> data = get_exported_file(fname);
- /*
- FileAccess *f=FileAccess::open(files[i],FileAccess::READ);
- if (!f) {
- EditorNode::add_io_error("Couldn't read: "+String(files[i]));
- }
- ERR_CONTINUE(!f);
- data.resize(f->get_len());
- f->get_buffer(data.ptr(),data.size());
-*/
- String dst_path=fname;
- dst_path=dst_path.replace_first("res://",asset_dir);
-
- da->make_dir_recursive(dst_path.get_base_dir());
-
- ep.step("Adding File: "+String(files[i]).get_file(),3+i*100/files.size());
-
- FileAccessRef fr = FileAccess::open(dst_path,FileAccess::WRITE);
- fr->store_buffer(data.ptr(),data.size());
+ FileAccess* dst = FileAccess::open(bar_dir+"/data.pck", FileAccess::WRITE);
+ if (!dst) {
+ EditorNode::add_io_error("Can't copy executable file to:\n "+p_path);
+ return ERR_FILE_CANT_WRITE;
}
-
+ save_pack(dst, false, 1024);
+ dst->close();
+ memdelete(dst);
ep.step("Creating BAR Package..",104);
String bb_packager=EditorSettings::get_singleton()->get("blackberry/host_tools");
bb_packager=bb_packager.plus_file("blackberry-nativepackager");
if (OS::get_singleton()->get_name()=="Windows")
- bb_packager+=".exe";
+ bb_packager+=".bat";
if (!FileAccess::exists(bb_packager)) {
@@ -482,7 +470,7 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
int ec;
- err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec);
+ Error err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec);
if (err!=OK)
return err;
@@ -493,7 +481,6 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
}
-
bool EditorExportPlatformBB10::poll_devices() {
bool dc=devices_changed;
@@ -537,7 +524,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
bb_deploy=bb_deploy.plus_file("blackberry-deploy");
bool windows = OS::get_singleton()->get_name()=="Windows";
if (windows)
- bb_deploy+=".exe";
+ bb_deploy+=".bat";
if (!FileAccess::exists(bb_deploy)) {
OS::get_singleton()->delay_usec(3000000);
@@ -639,7 +626,7 @@ Error EditorExportPlatformBB10::run(int p_device, bool p_dumb) {
String bb_deploy=EditorSettings::get_singleton()->get("blackberry/host_tools");
bb_deploy=bb_deploy.plus_file("blackberry-deploy");
if (OS::get_singleton()->get_name()=="Windows")
- bb_deploy+=".exe";
+ bb_deploy+=".bat";
if (!FileAccess::exists(bb_deploy)) {
EditorNode::add_io_error("Blackberry Deploy not found:\n"+bb_deploy);
diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp
index ff43a68b1d..d89033b1df 100644
--- a/platform/bb10/os_bb10.cpp
+++ b/platform/bb10/os_bb10.cpp
@@ -619,7 +619,7 @@ OSBB10::OSBB10() {
printf("godot bb10!\n");
getcwd(launch_dir, sizeof(launch_dir));
printf("launch dir %s\n", launch_dir);
- chdir("app/native/assets");
+ chdir("app/native");
launch_dir_ptr = launch_dir;
}
diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h
index a5b1b8731f..04334991fd 100755
--- a/platform/iphone/gl_view.h
+++ b/platform/iphone/gl_view.h
@@ -101,6 +101,8 @@
- (BOOL)createFramebuffer;
- (void)destroyFramebuffer;
+- (void)audioRouteChangeListenerCallback:(NSNotification*)notification;
+
@property NSTimeInterval animationInterval;
@end
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index 0625361b96..3d6c48ffaf 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -119,6 +119,8 @@ bool _play_video(String p_path, float p_volume, String p_audio_track, String p_s
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_instance.avPlayer currentItem]];
+ [_instance.avPlayer addObserver:_instance forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:0];
+
[_instance.avPlayerLayer setFrame:_instance.bounds];
[_instance.layer addSublayer:_instance.avPlayerLayer];
[_instance.avPlayer play];
@@ -610,6 +612,39 @@ static void clear_touches() {
printf("inserting text with character %i\n", character[0]);
};
+- (void)audioRouteChangeListenerCallback:(NSNotification*)notification
+{
+ printf("*********** route changed!%i\n");
+ NSDictionary *interuptionDict = notification.userInfo;
+
+ NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
+
+ switch (routeChangeReason) {
+
+ case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
+ NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
+ NSLog(@"Headphone/Line plugged in");
+ break;
+
+ case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
+ NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
+ NSLog(@"Headphone/Line was pulled. Resuming video play....");
+ if (_is_video_playing) {
+
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+ [_instance.avPlayer play]; // NOTE: change this line according your current player implementation
+ NSLog(@"resumed play");
+ });
+ };
+ break;
+
+ case AVAudioSessionRouteChangeReasonCategoryChange:
+ // called at start - also when other audio wants to play
+ NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");
+ break;
+ }
+}
+
// When created via code however, we get initWithFrame
-(id)initWithFrame:(CGRect)frame
@@ -625,6 +660,11 @@ static void clear_touches() {
init_touches();
self. multipleTouchEnabled = YES;
+ printf("******** adding observer for sound routing changes\n");
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:)
+ name:AVAudioSessionRouteChangeNotification
+ object:nil];
+
//self.autoresizesSubviews = YES;
//[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth];
@@ -674,6 +714,18 @@ static void clear_touches() {
video_current_time = kCMTimeZero;
}
}
+
+ if (object == _instance.avPlayer && [keyPath isEqualToString:@"rate"]) {
+ NSLog(@"Player playback rate changed: %.5f", _instance.avPlayer.rate);
+ if (_is_video_playing() && _instance.avPlayer.rate == 0.0 && !_instance.avPlayer.error) {
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+ [_instance.avPlayer play]; // NOTE: change this line according your current player implementation
+ NSLog(@"resumed play");
+ });
+
+ NSLog(@" . . . PAUSED (or just started)");
+ }
+ }
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 16dd695c59..9cdf04797c 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -1,4 +1,90 @@
-
+#
+# tested on | Windows native | Linux cross-compilation
+# ------------------------+-------------------+---------------------------
+# MSVS C++ 2010 Express | WORKS | n/a
+# Mingw-w64 | WORKS | WORKS
+# Mingw-w32 | WORKS | WORKS
+# MinGW | WORKS | untested
+#
+#####
+# Notes about MSVS C++ :
+#
+# - MSVC2010-Express compiles to 32bits only.
+#
+#####
+# Notes about Mingw-w64 and Mingw-w32 under Windows :
+#
+# - both can be installed using the official installer :
+# http://mingw-w64.sourceforge.net/download.php#mingw-builds
+#
+# - if you want to compile both 32bits and 64bits, don't forget to
+# run the installer twice to install them both.
+#
+# - install them into a path that does not contain spaces
+# ( example : "C:/Mingw-w32", "C:/Mingw-w64" )
+#
+# - if you want to compile faster using the "-j" option, don't forget
+# to install the appropriate version of the Pywin32 python extension
+# available from : http://sourceforge.net/projects/pywin32/files/
+#
+# - before running scons, you must add into the environment path
+# the path to the "/bin" directory of the Mingw version you want
+# to use :
+#
+# set PATH=C:/Mingw-w32/bin;%PATH%
+#
+# - then, scons should be able to detect gcc.
+# - Mingw-w32 only compiles 32bits.
+# - Mingw-w64 only compiles 64bits.
+#
+# - it is possible to add them both at the same time into the PATH env,
+# if you also define the MINGW32_PREFIX and MINGW64_PREFIX environment
+# variables.
+# For instance, you could store that set of commands into a .bat script
+# that you would run just before scons :
+#
+# set PATH=C:\mingw-w32\bin;%PATH%
+# set PATH=C:\mingw-w64\bin;%PATH%
+# set MINGW32_PREFIX=C:\mingw-w32\bin\
+# set MINGW64_PREFIX=C:\mingw-w64\bin\
+#
+#####
+# Notes about Mingw, Mingw-w64 and Mingw-w32 under Linux :
+#
+# - default toolchain prefixes are :
+# "i586-mingw32msvc-" for MinGW
+# "i686-w64-mingw32-" for Mingw-w32
+# "x86_64-w64-mingw32-" for Mingw-w64
+#
+# - if both MinGW and Mingw-w32 are installed on your system
+# Mingw-w32 should take the priority over MinGW.
+#
+# - it is possible to manually override prefixes by defining
+# the MINGW32_PREFIX and MINGW64_PREFIX environment variables.
+#
+#####
+# Notes about Mingw under Windows :
+#
+# - this is the MinGW version from http://mingw.org/
+# - install it into a path that does not contain spaces
+# ( example : "C:/MinGW" )
+# - several DirectX headers might be missing. You can copy them into
+# the C:/MinGW/include" directory from this page :
+# https://code.google.com/p/mingw-lib/source/browse/trunk/working/avcodec_to_widget_5/directx_include/
+# - before running scons, add the path to the "/bin" directory :
+# set PATH=C:/MinGW/bin;%PATH%
+# - scons should be able to detect gcc.
+#
+
+#####
+# TODO :
+#
+# - finish to cleanup this script to remove all the remains of previous hacks and workarounds
+# - make it work with the Windows7 SDK that is supposed to enable 64bits compilation for MSVC2010-Express
+# - confirm it works well with other Visual Studio versions.
+# - update the wiki about the pywin32 extension required for the "-j" option under Windows.
+# - update the wiki to document MINGW32_PREFIX and MINGW64_PREFIX
+#
import os
@@ -13,50 +99,70 @@ def get_name():
def can_build():
-
if (os.name=="nt"):
#building natively on windows!
if (os.getenv("VSINSTALLDIR")):
return True
else:
- print("MSVC Not detected, attempting mingw.")
+ print("\nMSVC not detected, attempting Mingw.")
+ mingw32 = ""
+ mingw64 = ""
+ if ( os.getenv("MINGW32_PREFIX") ) :
+ mingw32 = os.getenv("MINGW32_PREFIX")
+ if ( os.getenv("MINGW64_PREFIX") ) :
+ mingw64 = os.getenv("MINGW64_PREFIX")
+
+ test = "gcc --version > NUL 2>&1"
+ if os.system(test)!= 0 and os.system(mingw32+test)!=0 and os.system(mingw64+test)!=0 :
+ print("- could not detect gcc.")
+ print("Please, make sure a path to a Mingw /bin directory is accessible into the environment PATH.\n")
+ return False
+ else:
+ print("- gcc detected.")
+
return True
-
-
if (os.name=="posix"):
mingw = "i586-mingw32msvc-"
- mingw64 = "i686-w64-mingw32-"
+ mingw64 = "x86_64-w64-mingw32-"
+ mingw32 = "i686-w64-mingw32-"
+
if (os.getenv("MINGW32_PREFIX")):
- mingw=os.getenv("MINGW32_PREFIX")
+ mingw32=os.getenv("MINGW32_PREFIX")
+ mingw = mingw32
if (os.getenv("MINGW64_PREFIX")):
mingw64=os.getenv("MINGW64_PREFIX")
-
- if os.system(mingw+"gcc --version >/dev/null") == 0 or os.system(mingw64+"gcc --version >/dev/null") ==0:
+
+ test = "gcc --version >/dev/null"
+ if os.system(mingw+test) == 0 or os.system(mingw64+test) ==0 or os.system(mingw32+test) ==0 :
return True
-
-
return False
def get_opts():
mingw=""
+ mingw32=""
mingw64=""
- if (os.name!="nt"):
+ if ( os.name == "posix" ):
mingw = "i586-mingw32msvc-"
- mingw64 = "i686-w64-mingw32-"
- if (os.getenv("MINGW32_PREFIX")):
- mingw=os.getenv("MINGW32_PREFIX")
- if (os.getenv("MINGW64_PREFIX")):
- mingw64=os.getenv("MINGW64_PREFIX")
+ mingw32 = "i686-w64-mingw32-"
+ mingw64 = "x86_64-w64-mingw32-"
+
+ if os.system(mingw32+"gcc --version >/dev/null") != 0 :
+ mingw32 = mingw
+
+ if (os.getenv("MINGW32_PREFIX")):
+ mingw32=os.getenv("MINGW32_PREFIX")
+ mingw = mingw32
+ if (os.getenv("MINGW64_PREFIX")):
+ mingw64=os.getenv("MINGW64_PREFIX")
return [
- ('mingw_prefix','Mingw Prefix',mingw),
+ ('mingw_prefix','Mingw Prefix',mingw32),
('mingw_prefix_64','Mingw Prefix 64 bits',mingw64),
- ('mingw64_for_32','Use Mingw 64 for 32 Bits Build',"no"),
]
def get_flags():
@@ -115,7 +221,7 @@ def configure(env):
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
- LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32']
+ LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI','Shlwapi', 'wsock32', 'shell32','advapi32']
env.Append(LINKFLAGS=[p+env["LIBSUFFIX"] for p in LIBS])
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
@@ -140,13 +246,13 @@ def configure(env):
# http://www.scons.org/wiki/LongCmdLinesOnWin32
if (os.name=="nt"):
import subprocess
- def mySpawn(sh, escape, cmd, args, env):
- newargs = ' '.join(args[1:])
- cmdline = cmd + " " + newargs
+
+ def mySubProcess(cmdline,env):
+ #print "SPAWNED : " + cmdline
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
+ stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
data, err = proc.communicate()
rv = proc.wait()
if rv:
@@ -154,35 +260,45 @@ def configure(env):
print err
print "====="
return rv
+
+ def mySpawn(sh, escape, cmd, args, env):
+
+ newargs = ' '.join(args[1:])
+ cmdline = cmd + " " + newargs
+
+ rv=0
+ if len(cmdline) > 32000 and cmd.endswith("ar") :
+ cmdline = cmd + " " + args[1] + " " + args[2] + " "
+ for i in range(3,len(args)) :
+ rv = mySubProcess( cmdline + args[i], env )
+ if rv :
+ break
+ else:
+ rv = mySubProcess( cmdline, env )
+
+ return rv
+
env['SPAWN'] = mySpawn
#build using mingw
if (os.name=="nt"):
env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes
else:
- env["PROGSUFFIX"]=env["PROGSUFFIX"]+".exe"
+ env["PROGSUFFIX"]=env["PROGSUFFIX"]+".exe" # for linux cross-compilation
mingw_prefix=""
if (env["bits"]=="default"):
env["bits"]="32"
- use64=False
if (env["bits"]=="32"):
-
- if (env["mingw64_for_32"]=="yes"):
- env.Append(CCFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-static-libgcc'])
- env.Append(LINKFLAGS=['-static-libstdc++'])
- mingw_prefix=env["mingw_prefix_64"];
- else:
- mingw_prefix=env["mingw_prefix"];
-
-
+ env.Append(LINKFLAGS=['-static'])
+ env.Append(LINKFLAGS=['-static-libgcc'])
+ env.Append(LINKFLAGS=['-static-libstdc++'])
+ mingw_prefix=env["mingw_prefix"];
else:
- mingw_prefix=env["mingw_prefix_64"];
env.Append(LINKFLAGS=['-static'])
+ mingw_prefix=env["mingw_prefix_64"];
nulstr=""
@@ -193,10 +309,10 @@ def configure(env):
- if os.system(mingw_prefix+"gcc --version"+nulstr)!=0:
- #not really super consistent but..
- print("Can't find Windows compiler: "+mingw_prefix)
- sys.exit(255)
+ # if os.system(mingw_prefix+"gcc --version"+nulstr)!=0:
+ # #not really super consistent but..
+ # print("Can't find Windows compiler: "+mingw_prefix)
+ # sys.exit(255)
if (env["target"]=="release"):
@@ -229,13 +345,13 @@ def configure(env):
env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLEW_ENABLED'])
- env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
+ env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','shlwapi','wsock32','kernel32'])
- if (env["bits"]=="32" and env["mingw64_for_32"]!="yes"):
-# env.Append(LIBS=['gcc_s'])
- #--with-arch=i686
- env.Append(CPPFLAGS=['-march=i686'])
- env.Append(LINKFLAGS=['-march=i686'])
+ # if (env["bits"]=="32"):
+# # env.Append(LIBS=['gcc_s'])
+ # #--with-arch=i686
+ # env.Append(CPPFLAGS=['-march=i686'])
+ # env.Append(LINKFLAGS=['-march=i686'])
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 13f2c32e77..50c42448f4 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -715,9 +715,14 @@ String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps)
return "";
_snprintf( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEM);
- res = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
- if (res != ERROR_SUCCESS)
- return "";
+ res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
+ if (res != ERROR_SUCCESS)
+ {
+ res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey);
+ if (res != ERROR_SUCCESS)
+ return "";
+ }
+
sz = sizeof(buffer);
res = RegQueryValueEx(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buffer,
@@ -1857,6 +1862,7 @@ String OS_Windows::get_stdin_string(bool p_block) {
void OS_Windows::move_window_to_foreground() {
SetForegroundWindow(hWnd);
+ BringWindowToTop(hWnd);
}
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index fb5cdb5089..2519dd6fdf 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -38,6 +38,11 @@ def can_build():
if (x11_error):
print("xcursor not found.. x11 disabled.")
return False
+
+ x11_error=os.system("pkg-config xinerama --modversion > /dev/null ")
+ if (x11_error):
+ print("xinerama not found.. x11 disabled.")
+ return False
return True # X11 enabled
@@ -48,6 +53,7 @@ def get_opts():
('use_llvm','Use llvm compiler','no'),
('use_sanitizer','Use llvm compiler sanitize address','no'),
('pulseaudio','Detect & Use pulseaudio','yes'),
+ ('new_wm_api', 'Use experimental window management API','no'),
]
def get_flags():
@@ -147,3 +153,7 @@ def configure(env):
env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
#env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
+ if(env["new_wm_api"]=="yes"):
+ env.Append(CPPFLAGS=['-DNEW_WM_API'])
+ env.ParseConfig('pkg-config xinerama --cflags --libs')
+
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index ac1818d200..8196281732 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -36,6 +36,17 @@
#include "servers/physics/physics_server_sw.h"
#include "X11/Xutil.h"
+#ifdef NEW_WM_API
+#include "X11/Xatom.h"
+#include "X11/extensions/Xinerama.h"
+// ICCCM
+#define WM_NormalState 1L // window normal state
+#define WM_IconicState 3L // window minimized
+// EWMH
+#define _NET_WM_STATE_REMOVE 0L // remove/unset property
+#define _NET_WM_STATE_ADD 1L // add/set property
+#define _NET_WM_STATE_TOGGLE 2L // toggle property
+#endif
#include "main/main.h"
@@ -56,7 +67,7 @@
#include <X11/Xatom.h>
-#include "os/pc_joystick_map.h"
+//#include "os/pc_joystick_map.h"
#undef CursorShape
@@ -117,10 +128,10 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
if (xim == NULL) {
WARN_PRINT("XOpenIM failed");
- xim_style=NULL;
+ xim_style=0L;
} else {
::XIMStyles *xim_styles=NULL;
- xim_style=0;
+ xim_style=0L;
char *imvalret=NULL;
imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
if (imvalret != NULL || xim_styles == NULL) {
@@ -128,7 +139,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
}
if (xim_styles) {
- xim_style = 0;
+ xim_style = 0L;
for (int i=0;i<xim_styles->count_styles;i++) {
if (xim_styles->supported_styles[i] ==
@@ -162,14 +173,11 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
// maybe contextgl wants to be in charge of creating the window
//print_line("def videomode "+itos(current_videomode.width)+","+itos(current_videomode.height));
#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+
context_gl = memnew( ContextGL_X11( x11_display, x11_window,current_videomode, false ) );
context_gl->initialize();
- if (true) {
- rasterizer = memnew( RasterizerGLES2 );
- } else {
- //rasterizer = memnew( RasterizerGLES1 );
- };
+ rasterizer = memnew( RasterizerGLES2 );
#endif
visual_server = memnew( VisualServerRaster(rasterizer) );
@@ -179,9 +187,10 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD));
}
+#ifndef NEW_WM_API
// borderless fullscreen window mode
if (current_videomode.fullscreen) {
- // needed for lxde/openbox, possibly others
+ // needed for lxde/openbox, possibly others
Hints hints;
Atom property;
hints.flags = 2;
@@ -210,7 +219,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev);
}
- // disable resizeable window
+ // disable resizable window
if (!current_videomode.resizable) {
XSizeHints *xsh;
xsh = XAllocSizeHints();
@@ -226,7 +235,25 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
xsh->min_height = xwa.height;
xsh->max_height = xwa.height;
XSetWMNormalHints(x11_display, x11_window, xsh);
+ XFree(xsh);
}
+#else
+ capture_idle = 0;
+ minimized = false;
+ maximized = false;
+
+ if (current_videomode.fullscreen) {
+ //set_wm_border(false);
+ set_wm_fullscreen(true);
+ }
+ if (!current_videomode.resizable) {
+ int screen = get_screen();
+ Size2i screen_size = get_screen_size(screen);
+ set_window_size(screen_size);
+ set_resizable(false);
+ }
+#endif
+
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
@@ -264,19 +291,20 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
XChangeWindowAttributes(x11_display, x11_window,CWEventMask,&new_attr);
- XClassHint* classHint;
+ XClassHint* classHint;
- /* set the titlebar name */
- XStoreName(x11_display, x11_window, "Godot");
+ /* set the titlebar name */
+ XStoreName(x11_display, x11_window, "Godot");
- /* set the name and class hints for the window manager to use */
- classHint = XAllocClassHint();
- if (classHint) {
- classHint->res_name = "Godot";
- classHint->res_class = "Godot";
- }
- XSetClassHint(x11_display, x11_window, classHint);
- XFree(classHint);
+ /* set the name and class hints for the window manager to use */
+ classHint = XAllocClassHint();
+ if (classHint) {
+ char wmclass[] = "Godot";
+ classHint->res_name = wmclass;
+ classHint->res_class = wmclass;
+ }
+ XSetClassHint(x11_display, x11_window, classHint);
+ XFree(classHint);
wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true);
XSetWMProtocols(x11_display, x11_window, &wm_delete, 1);
@@ -468,8 +496,9 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
center.y = current_videomode.height/2;
XWarpPointer(x11_display, None, x11_window,
0,0,0,0, (int)center.x, (int)center.y);
- }
+ input->set_mouse_pos(center);
+ }
}
void OS_X11::warp_mouse_pos(const Point2& p_to) {
@@ -497,7 +526,6 @@ OS::MouseMode OS_X11::get_mouse_mode() const {
int OS_X11::get_mouse_button_state() const {
-
return last_button_state;
}
@@ -524,6 +552,344 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) cons
}
+#ifdef NEW_WM_API
+#if 0
+// Just now not needed. Can be used for a possible OS.set_border(bool) method
+void OS_X11::set_wm_border(bool p_enabled) {
+ // needed for lxde/openbox, possibly others
+ Hints hints;
+ Atom property;
+ hints.flags = 2;
+ hints.decorations = p_enabled ? 1L : 0L;
+ property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
+ XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ XMapRaised(x11_display, x11_window);
+ //XMoveResizeWindow(x11_display, x11_window, 0, 0, 800, 800);
+}
+#endif
+
+void OS_X11::set_wm_fullscreen(bool p_enabled) {
+ // Using EWMH -- Extened Window Manager Hints
+ XEvent xev;
+ Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
+ Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False);
+
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.xclient.window = x11_window;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+ xev.xclient.data.l[1] = wm_fullscreen;
+ xev.xclient.data.l[2] = 0;
+
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+}
+
+int OS_X11::get_screen_count() const {
+ // Using Xinerama Extension
+ int event_base, error_base;
+ const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
+ if( !ext_okay ) return 0;
+
+ int count;
+ XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count);
+ XFree(xsi);
+ return count;
+}
+
+int OS_X11::get_screen() const {
+ int x,y;
+ Window child;
+ XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child);
+
+ int count = get_screen_count();
+ for(int i=0; i<count; i++) {
+ Point2i pos = get_screen_position(i);
+ Size2i size = get_screen_size(i);
+ if( (x >= pos.x && x <pos.x + size.width) && (y >= pos.y && y < pos.y + size.height) )
+ return i;
+ }
+ return 0;
+}
+
+void OS_X11::set_screen(int p_screen) {
+ int count = get_screen_count();
+ if(p_screen >= count) return;
+
+ if( current_videomode.fullscreen ) {
+ Point2i position = get_screen_position(p_screen);
+ Size2i size = get_screen_size(p_screen);
+
+ XMoveResizeWindow(x11_display, x11_window, position.x, position.y, size.x, size.y);
+ }
+ else {
+ if( p_screen != get_screen() ) {
+ Point2i position = get_screen_position(p_screen);
+ XMoveWindow(x11_display, x11_window, position.x, position.y);
+ }
+ }
+}
+
+Point2 OS_X11::get_screen_position(int p_screen) const {
+ // Using Xinerama Extension
+ int event_base, error_base;
+ const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
+ if( !ext_okay ) return Point2i(0,0);
+
+ int count;
+ XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count);
+ if( p_screen >= count ) return Point2i(0,0);
+
+ Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org);
+ XFree(xsi);
+ return position;
+}
+
+Size2 OS_X11::get_screen_size(int p_screen) const {
+ // Using Xinerama Extension
+ int event_base, error_base;
+ const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
+ if( !ext_okay ) return Size2i(0,0);
+
+ int count;
+ XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count);
+ if( p_screen >= count ) return Size2i(0,0);
+
+ Size2i size = Point2i(xsi[p_screen].width, xsi[p_screen].height);
+ XFree(xsi);
+ return size;
+}
+
+
+Point2 OS_X11::get_window_position() const {
+ int x,y;
+ Window child;
+ XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child);
+
+ int screen = get_screen();
+ Point2i screen_position = get_screen_position(screen);
+
+ return Point2i(x-screen_position.x, y-screen_position.y);
+}
+
+void OS_X11::set_window_position(const Point2& p_position) {
+ // Using EWMH -- Extended Window Manager Hints
+ // to get the size of the decoration
+ Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True);
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = NULL;
+ int result;
+
+ result = XGetWindowProperty(
+ x11_display,
+ x11_window,
+ property,
+ 0,
+ 32,
+ False,
+ AnyPropertyType,
+ &type,
+ &format,
+ &len,
+ &remaining,
+ &data
+ );
+
+ long left = 0L;
+ long top = 0L;
+
+ if( result == Success ) {
+ long *extends = (long *) data;
+
+ left = extends[0];
+ top = extends[2];
+
+ XFree(data);
+ }
+
+ int screen = get_screen();
+ Point2i screen_position = get_screen_position(screen);
+
+ left -= screen_position.x;
+ top -= screen_position.y;
+
+ XMoveWindow(x11_display,x11_window,p_position.x - left,p_position.y - top);
+}
+
+Size2 OS_X11::get_window_size() const {
+ XWindowAttributes xwa;
+ XGetWindowAttributes(x11_display, x11_window, &xwa);
+ return Size2i(xwa.width, xwa.height);
+}
+
+void OS_X11::set_window_size(const Size2 p_size) {
+ XResizeWindow(x11_display, x11_window, p_size.x, p_size.y);
+}
+
+void OS_X11::set_fullscreen(bool p_enabled) {
+ set_wm_fullscreen(p_enabled);
+ current_videomode.fullscreen = p_enabled;
+
+ visual_server->init();
+}
+
+bool OS_X11::is_fullscreen() const {
+ return current_videomode.fullscreen;
+}
+
+void OS_X11::set_resizable(bool p_enabled) {
+ XSizeHints *xsh;
+ xsh = XAllocSizeHints();
+ xsh->flags = p_enabled ? 0L : PMinSize | PMaxSize;
+ if(!p_enabled) {
+ XWindowAttributes xwa;
+ XGetWindowAttributes(x11_display,x11_window,&xwa);
+ xsh->min_width = xwa.width;
+ xsh->max_width = xwa.width;
+ xsh->min_height = xwa.height;
+ xsh->max_height = xwa.height;
+ }
+ XSetWMNormalHints(x11_display, x11_window, xsh);
+ XFree(xsh);
+ current_videomode.resizable = p_enabled;
+}
+
+bool OS_X11::is_resizable() const {
+ return current_videomode.resizable;
+}
+
+void OS_X11::set_minimized(bool p_enabled) {
+ // Using ICCCM -- Inter-Client Communication Conventions Manual
+ XEvent xev;
+ Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False);
+
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.xclient.window = x11_window;
+ xev.xclient.message_type = wm_change;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = p_enabled ? WM_IconicState : WM_NormalState;
+
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+
+ //XEvent xev;
+ Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
+ Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False);
+
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.xclient.window = x11_window;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
+ xev.xclient.data.l[1] = wm_hidden;
+
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+}
+
+bool OS_X11::is_minimized() const {
+ // Using ICCCM -- Inter-Client Communication Conventions Manual
+ Atom property = XInternAtom(x11_display,"WM_STATE", True);
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = NULL;
+
+ int result = XGetWindowProperty(
+ x11_display,
+ x11_window,
+ property,
+ 0,
+ 32,
+ False,
+ AnyPropertyType,
+ &type,
+ &format,
+ &len,
+ &remaining,
+ &data
+ );
+
+ if( result == Success ) {
+ long *state = (long *) data;
+ if( state[0] == WM_IconicState )
+ return true;
+ }
+ return false;
+}
+
+void OS_X11::set_maximized(bool p_enabled) {
+ // Using EWMH -- Extended Window Manager Hints
+ XEvent xev;
+ Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
+ Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+ Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.xclient.window = x11_window;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+ xev.xclient.data.l[1] = wm_max_horz;
+ xev.xclient.data.l[2] = wm_max_vert;
+
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+
+ maximized = p_enabled;
+}
+
+bool OS_X11::is_maximized() const {
+ // Using EWMH -- Extended Window Manager Hints
+ Atom property = XInternAtom(x11_display,"_NET_WM_STATE",False );
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = NULL;
+
+ int result = XGetWindowProperty(
+ x11_display,
+ x11_window,
+ property,
+ 0,
+ 1024,
+ False,
+ XA_ATOM,
+ &type,
+ &format,
+ &len,
+ &remaining,
+ &data
+ );
+
+ if(result == Success) {
+ Atom *atoms = (Atom*) data;
+ Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+ Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+ bool found_wm_max_horz = false;
+ bool found_wm_max_vert = false;
+
+ for( unsigned int i=0; i < len; i++ ) {
+ if( atoms[i] == wm_max_horz )
+ found_wm_max_horz = true;
+ if( atoms[i] == wm_max_vert )
+ found_wm_max_vert = true;
+
+ if( found_wm_max_horz && found_wm_max_vert )
+ return true;
+ }
+ XFree(atoms);
+ }
+
+ return false;
+}
+#endif
InputModifierState OS_X11::get_key_modifier_state(unsigned int p_x11_state) {
@@ -598,11 +964,9 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
KeySym keysym_keycode=0; // keysym used to find a keycode
KeySym keysym_unicode=0; // keysym used to find unicode
- int nbytes=0; // bytes the string takes
-
// XLookupString returns keysyms usable as nice scancodes/
char str[256+1];
- nbytes=XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL);
+ XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL);
// Meanwhile, XLookupString returns keysyms useful for unicode.
@@ -699,7 +1063,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
::Time tresh=ABS(peek_event.xkey.time-xkeyevent->time);
if (peek_event.type == KeyPress && tresh<5 ) {
KeySym rk;
- nbytes=XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL);
+ XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL);
if (rk==keysym_keycode) {
XEvent event;
XNextEvent(x11_display, &event); //erase next event
@@ -763,13 +1127,18 @@ void OS_X11::process_xevents() {
break;
case VisibilityNotify: {
-
XVisibilityEvent * visibility = (XVisibilityEvent *)&event;
minimized = (visibility->state == VisibilityFullyObscured);
-
} break;
- case FocusIn:
+ case FocusIn:
+ minimized = false;
+#ifdef NEW_WM_API
+ if(current_videomode.fullscreen) {
+ set_wm_fullscreen(true);
+ visual_server->init();
+ }
+#endif
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
if (mouse_mode==MOUSE_MODE_CAPTURED) {
XGrabPointer(x11_display, x11_window, True,
@@ -780,6 +1149,13 @@ void OS_X11::process_xevents() {
break;
case FocusOut:
+#ifdef NEW_WM_API
+ if(current_videomode.fullscreen) {
+ set_wm_fullscreen(false);
+ set_minimized(true);
+ visual_server->init();
+ }
+#endif
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
if (mouse_mode==MOUSE_MODE_CAPTURED) {
//dear X11, I try, I really try, but you never work, you do whathever you want.
@@ -806,7 +1182,7 @@ void OS_X11::process_xevents() {
event.xbutton.x=last_mouse_pos.x;
event.xbutton.y=last_mouse_pos.y;
}
-
+
InputEvent mouse_event;
mouse_event.ID=++event_id;
mouse_event.type = InputEvent::MOUSE_BUTTON;
@@ -841,7 +1217,7 @@ void OS_X11::process_xevents() {
last_click_ms+=diff;
last_click_pos = Point2(event.xbutton.x,event.xbutton.y);
}
- }
+ }
input->parse_input_event( mouse_event);
@@ -851,16 +1227,15 @@ void OS_X11::process_xevents() {
last_timestamp=event.xmotion.time;
-
+
// Motion is also simple.
// A little hack is in order
// to be able to send relative motion events.
-
Point2i pos( event.xmotion.x, event.xmotion.y );
if (mouse_mode==MOUSE_MODE_CAPTURED) {
#if 1
- Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2);
+ //Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2);
if (pos==Point2i(current_videomode.width/2,current_videomode.height/2)) {
//this sucks, it's a hack, etc and is a little inaccurate, etc.
//but nothing I can do, X11 sucks.
@@ -869,9 +1244,9 @@ void OS_X11::process_xevents() {
break;
}
- Point2i ncenter = pos;
- pos = last_mouse_pos + ( pos-center );
- center=ncenter;
+ Point2i new_center = pos;
+ pos = last_mouse_pos + ( pos - center );
+ center=new_center;
do_mouse_warp=true;
#else
//Dear X11, thanks for making my life miserable
@@ -884,9 +1259,7 @@ void OS_X11::process_xevents() {
XWarpPointer(x11_display, None, x11_window,
0,0,0,0, (int)center.x, (int)center.y);
#endif
-
}
-
if (!last_mouse_pos_valid) {
@@ -895,7 +1268,14 @@ void OS_X11::process_xevents() {
}
Point2i rel = pos - last_mouse_pos;
-
+
+#ifdef NEW_WM_API
+ if (mouse_mode==MOUSE_MODE_CAPTURED) {
+ pos.x = current_videomode.width / 2;
+ pos.y = current_videomode.height / 2;
+ }
+#endif
+
InputEvent motion_event;
motion_event.ID=++event_id;
motion_event.type=InputEvent::MOUSE_MOTION;
@@ -915,6 +1295,8 @@ void OS_X11::process_xevents() {
motion_event.mouse_motion.relative_y=rel.y;
last_mouse_pos=pos;
+
+ // printf("rel: %d,%d\n", rel.x, rel.y );
input->parse_input_event( motion_event);
@@ -989,8 +1371,18 @@ void OS_X11::process_xevents() {
if (do_mouse_warp) {
XWarpPointer(x11_display, None, x11_window,
- 0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2);
-
+ 0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2);
+
+ /*
+ Window root, child;
+ int root_x, root_y;
+ int win_x, win_y;
+ unsigned int mask;
+ XQueryPointer( x11_display, x11_window, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask );
+
+ printf("Root: %d,%d\n", root_x, root_y);
+ printf("Win: %d,%d\n", win_x, win_y);
+ */
}
}
@@ -1358,6 +1750,7 @@ void OS_X11::process_joysticks() {
#endif
};
+
void OS_X11::set_cursor_shape(CursorShape p_shape) {
ERR_FAIL_INDEX(p_shape,CURSOR_MAX);
@@ -1470,8 +1863,6 @@ OS_X11::OS_X11() {
#endif
minimized = false;
- xim_style=NULL;
+ xim_style=0L;
mouse_mode=MOUSE_MODE_VISIBLE;
-
-
};
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index dd2476ec1b..ffa1ce00b3 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -159,6 +159,12 @@ class OS_X11 : public OS_Unix {
int joystick_count;
Joystick joysticks[JOYSTICKS_MAX];
+#ifdef NEW_WM_API
+ unsigned int capture_idle;
+ bool maximized;
+ //void set_wm_border(bool p_enabled);
+ void set_wm_fullscreen(bool p_enabled);
+#endif
protected:
@@ -166,8 +172,8 @@ protected:
virtual const char * get_video_driver_name(int p_driver) const;
virtual VideoMode get_default_video_mode() const;
- virtual int get_audio_driver_count() const;
- virtual const char * get_audio_driver_name(int p_driver) const;
+ virtual int get_audio_driver_count() const;
+ virtual const char * get_audio_driver_name(int p_driver) const;
virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver);
virtual void finalize();
@@ -178,6 +184,7 @@ protected:
void process_joysticks();
void close_joystick(int p_id = -1);
+
public:
virtual String get_name();
@@ -213,6 +220,25 @@ public:
virtual VideoMode get_video_mode(int p_screen=0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
+#ifdef NEW_WM_API
+ virtual int get_screen_count() const;
+ virtual int get_screen() const;
+ virtual void set_screen(int p_screen);
+ virtual Point2 get_screen_position(int p_screen=0) const;
+ virtual Size2 get_screen_size(int p_screen=0) const;
+ virtual Point2 get_window_position() const;
+ virtual void set_window_position(const Point2& p_position);
+ virtual Size2 get_window_size() const;
+ virtual void set_window_size(const Size2 p_size);
+ virtual void set_fullscreen(bool p_enabled);
+ virtual bool is_fullscreen() const;
+ virtual void set_resizable(bool p_enabled);
+ virtual bool is_resizable() const;
+ virtual void set_minimized(bool p_enabled);
+ virtual bool is_minimized() const;
+ virtual void set_maximized(bool p_enabled);
+ virtual bool is_maximized() const;
+#endif
virtual void move_window_to_foreground();
void run();
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index fce21f6001..a5c455ce64 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -216,6 +216,119 @@ void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_b
}
+
+void Area2D::_area_enter_tree(ObjectID p_id) {
+
+ Object *obj = ObjectDB::get_instance(p_id);
+ Node *node = obj ? obj->cast_to<Node>() : NULL;
+ ERR_FAIL_COND(!node);
+
+ Map<ObjectID,AreaState>::Element *E=area_map.find(p_id);
+ ERR_FAIL_COND(!E);
+ ERR_FAIL_COND(E->get().in_tree);
+
+ E->get().in_tree=true;
+ emit_signal(SceneStringNames::get_singleton()->area_enter,node);
+ for(int i=0;i<E->get().shapes.size();i++) {
+
+ emit_signal(SceneStringNames::get_singleton()->area_enter_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape);
+ }
+
+}
+
+void Area2D::_area_exit_tree(ObjectID p_id) {
+
+ Object *obj = ObjectDB::get_instance(p_id);
+ Node *node = obj ? obj->cast_to<Node>() : NULL;
+ ERR_FAIL_COND(!node);
+ Map<ObjectID,AreaState>::Element *E=area_map.find(p_id);
+ ERR_FAIL_COND(!E);
+ ERR_FAIL_COND(!E->get().in_tree);
+ E->get().in_tree=false;
+ emit_signal(SceneStringNames::get_singleton()->area_exit,node);
+ for(int i=0;i<E->get().shapes.size();i++) {
+
+ emit_signal(SceneStringNames::get_singleton()->area_exit_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape);
+ }
+
+}
+
+void Area2D::_area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape) {
+
+ bool area_in = p_status==Physics2DServer::AREA_BODY_ADDED;
+ ObjectID objid=p_instance;
+
+ Object *obj = ObjectDB::get_instance(objid);
+ Node *node = obj ? obj->cast_to<Node>() : NULL;
+
+ Map<ObjectID,AreaState>::Element *E=area_map.find(objid);
+
+ ERR_FAIL_COND(!area_in && !E);
+
+ locked=true;
+
+ if (area_in) {
+ if (!E) {
+
+ E = area_map.insert(objid,AreaState());
+ E->get().rc=0;
+ E->get().in_tree=node && node->is_inside_tree();
+ if (node) {
+ node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree,make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree,make_binds(objid));
+ if (E->get().in_tree) {
+ emit_signal(SceneStringNames::get_singleton()->area_enter,node);
+ }
+ }
+
+ }
+ E->get().rc++;
+ if (node)
+ E->get().shapes.insert(AreaShapePair(p_area_shape,p_self_shape));
+
+
+ if (!node || E->get().in_tree) {
+ emit_signal(SceneStringNames::get_singleton()->area_enter_shape,objid,node,p_area_shape,p_self_shape);
+ }
+
+ } else {
+
+ E->get().rc--;
+
+ if (node)
+ E->get().shapes.erase(AreaShapePair(p_area_shape,p_self_shape));
+
+ bool eraseit=false;
+
+ if (E->get().rc==0) {
+
+ if (node) {
+ node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree);
+ node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree);
+ if (E->get().in_tree)
+ emit_signal(SceneStringNames::get_singleton()->area_exit,obj);
+
+ }
+
+ eraseit=true;
+
+ }
+ if (!node || E->get().in_tree) {
+ emit_signal(SceneStringNames::get_singleton()->area_exit_shape,objid,obj,p_area_shape,p_self_shape);
+ }
+
+ if (eraseit)
+ area_map.erase(E);
+
+ }
+
+ locked=false;
+
+
+}
+
+
+
void Area2D::_clear_monitoring() {
if (locked) {
@@ -223,27 +336,56 @@ void Area2D::_clear_monitoring() {
}
ERR_FAIL_COND(locked);
- Map<ObjectID,BodyState> bmcopy = body_map;
- body_map.clear();
- //disconnect all monitored stuff
+ {
+ Map<ObjectID,BodyState> bmcopy = body_map;
+ body_map.clear();
+ //disconnect all monitored stuff
- for (Map<ObjectID,BodyState>::Element *E=bmcopy.front();E;E=E->next()) {
+ for (Map<ObjectID,BodyState>::Element *E=bmcopy.front();E;E=E->next()) {
- Object *obj = ObjectDB::get_instance(E->key());
- Node *node = obj ? obj->cast_to<Node>() : NULL;
- ERR_CONTINUE(!node);
- if (!E->get().in_tree)
- continue;
+ Object *obj = ObjectDB::get_instance(E->key());
+ Node *node = obj ? obj->cast_to<Node>() : NULL;
+ ERR_CONTINUE(!node);
+ if (!E->get().in_tree)
+ continue;
- for(int i=0;i<E->get().shapes.size();i++) {
+ for(int i=0;i<E->get().shapes.size();i++) {
- emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
+ emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
+ }
+
+ emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
+
+ node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree);
+ node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree);
}
- emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
+ }
- node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree);
+ {
+
+ Map<ObjectID,AreaState> bmcopy = area_map;
+ area_map.clear();
+ //disconnect all monitored stuff
+
+ for (Map<ObjectID,AreaState>::Element *E=bmcopy.front();E;E=E->next()) {
+
+ Object *obj = ObjectDB::get_instance(E->key());
+ Node *node = obj ? obj->cast_to<Node>() : NULL;
+ ERR_CONTINUE(!node);
+ if (!E->get().in_tree)
+ continue;
+
+ for(int i=0;i<E->get().shapes.size();i++) {
+
+ emit_signal(SceneStringNames::get_singleton()->area_exit_shape,E->key(),node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape);
+ }
+
+ emit_signal(SceneStringNames::get_singleton()->area_exit,obj);
+
+ node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree);
+ node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree);
+ }
}
}
@@ -276,8 +418,10 @@ void Area2D::set_enable_monitoring(bool p_enable) {
if (monitoring) {
Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout");
+ Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,"_area_inout");
} else {
Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName());
+ Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(),NULL,StringName());
_clear_monitoring();
}
@@ -288,6 +432,26 @@ bool Area2D::is_monitoring_enabled() const {
return monitoring;
}
+void Area2D::set_monitorable(bool p_enable) {
+
+ if (locked) {
+ ERR_EXPLAIN("This function can't be used during the in/out signal.");
+ }
+ ERR_FAIL_COND(locked);
+
+ if (p_enable==monitorable)
+ return;
+
+ monitorable=p_enable;
+
+ Physics2DServer::get_singleton()->area_set_monitorable(get_rid(),monitorable);
+}
+
+bool Area2D::is_monitorable() const {
+
+ return monitorable;
+}
+
Array Area2D::get_overlapping_bodies() const {
ERR_FAIL_COND_V(!monitoring,Array());
@@ -307,12 +471,56 @@ Array Area2D::get_overlapping_bodies() const {
return ret;
}
+Array Area2D::get_overlapping_areas() const {
+
+ ERR_FAIL_COND_V(!monitoring,Array());
+ Array ret;
+ ret.resize(area_map.size());
+ int idx=0;
+ for (const Map<ObjectID,AreaState>::Element *E=area_map.front();E;E=E->next()) {
+ Object *obj = ObjectDB::get_instance(E->key());
+ if (!obj) {
+ ret.resize( ret.size() -1 ); //ops
+ } else {
+ ret[idx++]=obj;
+ }
+
+ }
+
+ return ret;
+}
+
+bool Area2D::overlaps_area(Node* p_area) const {
+
+ ERR_FAIL_NULL_V(p_area,false);
+ const Map<ObjectID,AreaState>::Element *E=area_map.find(p_area->get_instance_ID());
+ if (!E)
+ return false;
+ return E->get().in_tree;
+
+
+
+}
+
+bool Area2D::overlaps_body(Node* p_body) const{
+
+ ERR_FAIL_NULL_V(p_body,false);
+ const Map<ObjectID,BodyState>::Element *E=body_map.find(p_body->get_instance_ID());
+ if (!E)
+ return false;
+ return E->get().in_tree;
+
+}
+
void Area2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_body_enter_tree","id"),&Area2D::_body_enter_tree);
ObjectTypeDB::bind_method(_MD("_body_exit_tree","id"),&Area2D::_body_exit_tree);
+ ObjectTypeDB::bind_method(_MD("_area_enter_tree","id"),&Area2D::_area_enter_tree);
+ ObjectTypeDB::bind_method(_MD("_area_exit_tree","id"),&Area2D::_area_exit_tree);
+
ObjectTypeDB::bind_method(_MD("set_space_override_mode","enable"),&Area2D::set_space_override_mode);
ObjectTypeDB::bind_method(_MD("get_space_override_mode"),&Area2D::get_space_override_mode);
@@ -337,15 +545,29 @@ void Area2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area2D::set_enable_monitoring);
ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area2D::is_monitoring_enabled);
+ ObjectTypeDB::bind_method(_MD("set_monitorable","enable"),&Area2D::set_monitorable);
+ ObjectTypeDB::bind_method(_MD("is_monitorable"),&Area2D::is_monitorable);
+
ObjectTypeDB::bind_method(_MD("get_overlapping_bodies"),&Area2D::get_overlapping_bodies);
+ ObjectTypeDB::bind_method(_MD("get_overlapping_areas"),&Area2D::get_overlapping_areas);
+
+ ObjectTypeDB::bind_method(_MD("overlaps_body:PhysicsBody2D","body"),&Area2D::overlaps_body);
+ ObjectTypeDB::bind_method(_MD("overlaps_area:Area2D","area"),&Area2D::overlaps_area);
ObjectTypeDB::bind_method(_MD("_body_inout"),&Area2D::_body_inout);
+ ObjectTypeDB::bind_method(_MD("_area_inout"),&Area2D::_area_inout);
+
+
+ ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
+ ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
+ ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D")));
+ ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D")));
+ ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape")));
+ ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape")));
+ ADD_SIGNAL( MethodInfo("area_enter",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D")));
+ ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D")));
- ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
- ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
- ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body")));
- ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
@@ -355,6 +577,7 @@ void Area2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
}
@@ -369,7 +592,9 @@ Area2D::Area2D() : CollisionObject2D(Physics2DServer::get_singleton()->area_crea
locked=false;
priority=0;
monitoring=false;
+ monitorable=false;
set_enable_monitoring(true);
+ set_monitorable(true);
}
diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h
index f770e88a19..6a6c757e0c 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/area_2d.h
@@ -53,6 +53,7 @@ private:
real_t angular_damp;
int priority;
bool monitoring;
+ bool monitorable;
bool locked;
void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape);
@@ -84,6 +85,36 @@ private:
Map<ObjectID,BodyState> body_map;
+
+
+ void _area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape);
+
+ void _area_enter_tree(ObjectID p_id);
+ void _area_exit_tree(ObjectID p_id);
+
+ struct AreaShapePair {
+
+ int area_shape;
+ int self_shape;
+ bool operator<(const AreaShapePair& p_sp) const {
+ if (area_shape==p_sp.area_shape)
+ return self_shape < p_sp.self_shape;
+ else
+ return area_shape < p_sp.area_shape;
+ }
+
+ AreaShapePair() {}
+ AreaShapePair(int p_bs, int p_as) { area_shape=p_bs; self_shape=p_as; }
+ };
+
+ struct AreaState {
+
+ int rc;
+ bool in_tree;
+ VSet<AreaShapePair> shapes;
+ };
+
+ Map<ObjectID,AreaState> area_map;
void _clear_monitoring();
@@ -117,8 +148,14 @@ public:
void set_enable_monitoring(bool p_enable);
bool is_monitoring_enabled() const;
+ void set_monitorable(bool p_enable);
+ bool is_monitorable() const;
+
Array get_overlapping_bodies() const; //function for script
+ Array get_overlapping_areas() const; //function for script
+ bool overlaps_area(Node* p_area) const;
+ bool overlaps_body(Node* p_body) const;
Area2D();
~Area2D();
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
new file mode 100644
index 0000000000..245b3ba7eb
--- /dev/null
+++ b/scene/2d/back_buffer_copy.cpp
@@ -0,0 +1,75 @@
+#include "back_buffer_copy.h"
+
+void BackBufferCopy::_update_copy_mode() {
+
+ switch(copy_mode) {
+
+ case COPY_MODE_DISALED: {
+
+ VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),false,Rect2());
+ } break;
+ case COPY_MODE_RECT: {
+
+ VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),true,rect);
+ } break;
+ case COPY_MODE_VIEWPORT: {
+
+ VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),true,Rect2());
+
+ } break;
+
+ }
+}
+
+Rect2 BackBufferCopy::get_item_rect() const {
+
+ return rect;
+}
+
+void BackBufferCopy::set_rect(const Rect2& p_rect) {
+
+ rect=p_rect;
+ _update_copy_mode();
+}
+
+Rect2 BackBufferCopy::get_rect() const{
+ return rect;
+}
+
+void BackBufferCopy::set_copy_mode(CopyMode p_mode){
+
+ copy_mode=p_mode;
+ _update_copy_mode();
+}
+BackBufferCopy::CopyMode BackBufferCopy::get_copy_mode() const{
+
+ return copy_mode;
+}
+
+
+void BackBufferCopy::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_rect","rect"),&BackBufferCopy::set_rect);
+ ObjectTypeDB::bind_method(_MD("get_rect"),&BackBufferCopy::get_rect);
+
+ ObjectTypeDB::bind_method(_MD("set_copy_mode","copy_mode"),&BackBufferCopy::set_copy_mode);
+ ObjectTypeDB::bind_method(_MD("get_copy_mode"),&BackBufferCopy::get_copy_mode);
+
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"copy_mode",PROPERTY_HINT_ENUM,"Disabled,Rect,Viewport"),_SCS("set_copy_mode"),_SCS("get_copy_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),_SCS("set_rect"),_SCS("get_rect"));
+
+ BIND_CONSTANT( COPY_MODE_DISALED );
+ BIND_CONSTANT( COPY_MODE_RECT );
+ BIND_CONSTANT( COPY_MODE_VIEWPORT );
+
+}
+
+BackBufferCopy::BackBufferCopy(){
+
+ rect=Rect2(-100,-100,200,200);
+ copy_mode=COPY_MODE_RECT;
+ _update_copy_mode();
+}
+BackBufferCopy::~BackBufferCopy(){
+
+}
diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h
new file mode 100644
index 0000000000..3a86ffa309
--- /dev/null
+++ b/scene/2d/back_buffer_copy.h
@@ -0,0 +1,41 @@
+#ifndef BACKBUFFERCOPY_H
+#define BACKBUFFERCOPY_H
+
+#include "scene/2d/node_2d.h"
+
+class BackBufferCopy : public Node2D {
+ OBJ_TYPE( BackBufferCopy,Node2D);
+public:
+ enum CopyMode {
+ COPY_MODE_DISALED,
+ COPY_MODE_RECT,
+ COPY_MODE_VIEWPORT
+ };
+private:
+
+ Rect2 rect;
+ CopyMode copy_mode;
+
+ void _update_copy_mode();
+
+protected:
+
+ static void _bind_methods();
+
+public:
+
+ void set_rect(const Rect2& p_rect);
+ Rect2 get_rect() const;
+
+ void set_copy_mode(CopyMode p_mode);
+ CopyMode get_copy_mode() const;
+
+ Rect2 get_item_rect() const;
+
+ BackBufferCopy();
+ ~BackBufferCopy();
+};
+
+VARIANT_ENUM_CAST(BackBufferCopy::CopyMode);
+
+#endif // BACKBUFFERCOPY_H
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index b3897010bf..b2d74b4ad5 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -323,6 +323,16 @@ void Camera2D::make_current() {
}
}
+void Camera2D::clear_current() {
+
+ current=false;
+ if (is_inside_tree()) {
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,group_name,"_make_current",(Object*)(NULL));
+ }
+
+}
+
+
void Camera2D::set_limit(Margin p_margin,int p_limit) {
ERR_FAIL_INDEX(p_margin,4);
@@ -435,6 +445,7 @@ void Camera2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_rotating"),&Camera2D::is_rotating);
ObjectTypeDB::bind_method(_MD("make_current"),&Camera2D::make_current);
+ ObjectTypeDB::bind_method(_MD("clear_current"),&Camera2D::clear_current);
ObjectTypeDB::bind_method(_MD("_make_current"),&Camera2D::_make_current);
ObjectTypeDB::bind_method(_MD("_update_scroll"),&Camera2D::_update_scroll);
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 116169cac1..515f9711bf 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -26,97 +26,98 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAMERA_2D_H
-#define CAMERA_2D_H
-
-#include "scene/2d/node_2d.h"
-#include "scene/main/viewport.h"
-
-
-class Camera2D : public Node2D {
-
- OBJ_TYPE( Camera2D, Node2D );
-
-protected:
- Point2 camera_pos;
- Point2 smoothed_camera_pos;
- bool first;
-
- Viewport *viewport;
-
- StringName group_name;
- StringName canvas_group_name;
- RID canvas;
- Vector2 offset;
- Vector2 zoom;
- bool centered;
- bool rotating;
- bool current;
- float smoothing;
- int limit[4];
- float drag_margin[4];
-
- bool h_drag_enabled;
- bool v_drag_enabled;
- float h_ofs;
- float v_ofs;
-
-
- Point2 camera_screen_center;
- void _update_scroll();
-
- void _make_current(Object *p_which);
- void _set_current(bool p_current);
-protected:
-
- virtual Matrix32 get_camera_transform();
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_offset(const Vector2& p_offset);
- Vector2 get_offset() const;
-
- void set_centered(bool p_centered);
- bool is_centered() const;
-
- void set_rotating(bool p_rotating);
- bool is_rotating() const;
-
- void set_limit(Margin p_margin,int p_limit);
- int get_limit(Margin p_margin) const;
-
-
- void set_h_drag_enabled(bool p_enabled);
- bool is_h_drag_enabled() const;
-
- void set_v_drag_enabled(bool p_enabled);
- bool is_v_drag_enabled() const;
-
- void set_drag_margin(Margin p_margin,float p_drag_margin);
- float get_drag_margin(Margin p_margin) const;
-
- void set_v_offset(float p_offset);
- float get_v_offset() const;
-
- void set_h_offset(float p_offset);
- float get_h_offset() const;
-
- void set_follow_smoothing(float p_speed);
- float get_follow_smoothing() const;
-
- void make_current();
- bool is_current() const;
-
- void set_zoom(const Vector2& p_zoom);
- Vector2 get_zoom() const;
-
- Point2 get_camera_screen_center() const;
-
- Vector2 get_camera_pos() const;
- void force_update_scroll();
-
- Camera2D();
-};
-
-#endif // CAMERA_2D_H
+#ifndef CAMERA_2D_H
+#define CAMERA_2D_H
+
+#include "scene/2d/node_2d.h"
+#include "scene/main/viewport.h"
+
+
+class Camera2D : public Node2D {
+
+ OBJ_TYPE( Camera2D, Node2D );
+
+protected:
+ Point2 camera_pos;
+ Point2 smoothed_camera_pos;
+ bool first;
+
+ Viewport *viewport;
+
+ StringName group_name;
+ StringName canvas_group_name;
+ RID canvas;
+ Vector2 offset;
+ Vector2 zoom;
+ bool centered;
+ bool rotating;
+ bool current;
+ float smoothing;
+ int limit[4];
+ float drag_margin[4];
+
+ bool h_drag_enabled;
+ bool v_drag_enabled;
+ float h_ofs;
+ float v_ofs;
+
+
+ Point2 camera_screen_center;
+ void _update_scroll();
+
+ void _make_current(Object *p_which);
+ void _set_current(bool p_current);
+protected:
+
+ virtual Matrix32 get_camera_transform();
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_offset(const Vector2& p_offset);
+ Vector2 get_offset() const;
+
+ void set_centered(bool p_centered);
+ bool is_centered() const;
+
+ void set_rotating(bool p_rotating);
+ bool is_rotating() const;
+
+ void set_limit(Margin p_margin,int p_limit);
+ int get_limit(Margin p_margin) const;
+
+
+ void set_h_drag_enabled(bool p_enabled);
+ bool is_h_drag_enabled() const;
+
+ void set_v_drag_enabled(bool p_enabled);
+ bool is_v_drag_enabled() const;
+
+ void set_drag_margin(Margin p_margin,float p_drag_margin);
+ float get_drag_margin(Margin p_margin) const;
+
+ void set_v_offset(float p_offset);
+ float get_v_offset() const;
+
+ void set_h_offset(float p_offset);
+ float get_h_offset() const;
+
+ void set_follow_smoothing(float p_speed);
+ float get_follow_smoothing() const;
+
+ void make_current();
+ void clear_current();
+ bool is_current() const;
+
+ void set_zoom(const Vector2& p_zoom);
+ Vector2 get_zoom() const;
+
+ Point2 get_camera_screen_center() const;
+
+ Vector2 get_camera_pos() const;
+ void force_update_scroll();
+
+ Camera2D();
+};
+
+#endif // CAMERA_2D_H
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 223adaf9bb..c3ff03d8f4 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -36,6 +36,191 @@
#include "scene/resources/texture.h"
#include "scene/resources/style_box.h"
+
+bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value) {
+
+ if (p_name==SceneStringNames::get_singleton()->shader_shader) {
+ set_shader(p_value);
+ return true;
+ } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+ set_unshaded(p_value);
+ return true;
+ } else {
+
+ if (shader.is_valid()) {
+
+
+ StringName pr = shader->remap_param(p_name);
+ if (!pr) {
+ String n = p_name;
+ if (n.find("param/")==0) { //backwards compatibility
+ pr = n.substr(6,n.length());
+ }
+ }
+ if (pr) {
+ VisualServer::get_singleton()->canvas_item_material_set_shader_param(material,pr,p_value);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
+
+
+ if (p_name==SceneStringNames::get_singleton()->shader_shader) {
+
+ r_ret=get_shader();
+ return true;
+ } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+
+
+ r_ret=unshaded;
+ return true;
+ } else {
+
+ if (shader.is_valid()) {
+
+ StringName pr = shader->remap_param(p_name);
+ if (pr) {
+ r_ret=VisualServer::get_singleton()->canvas_item_material_get_shader_param(material,pr);
+ return true;
+ }
+ }
+
+ }
+
+
+ return false;
+}
+
+
+void CanvasItemMaterial::_get_property_list( List<PropertyInfo> *p_list) const {
+
+ p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) );
+ p_list->push_back( PropertyInfo( Variant::BOOL, "shader/unshaded") );
+
+ if (!shader.is_null()) {
+
+ shader->get_param_list(p_list);
+ }
+
+}
+
+void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) {
+
+ ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
+#ifdef TOOLS_ENABLED
+
+ if (shader.is_valid()) {
+ shader->disconnect("changed",this,"_shader_changed");
+ }
+#endif
+ shader=p_shader;
+
+#ifdef TOOLS_ENABLED
+
+ if (shader.is_valid()) {
+ shader->connect("changed",this,"_shader_changed");
+ }
+#endif
+
+ RID rid;
+ if (shader.is_valid())
+ rid=shader->get_rid();
+
+ VS::get_singleton()->canvas_item_material_set_shader(material,rid);
+ _change_notify(); //properties for shader exposed
+ emit_changed();
+}
+
+Ref<Shader> CanvasItemMaterial::get_shader() const{
+
+ return shader;
+}
+
+void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){
+
+ VS::get_singleton()->canvas_item_material_set_shader_param(material,p_param,p_value);
+}
+
+Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
+
+ return VS::get_singleton()->canvas_item_material_get_shader_param(material,p_param);
+}
+
+void CanvasItemMaterial::_shader_changed() {
+
+
+}
+
+RID CanvasItemMaterial::get_rid() const {
+
+ return material;
+}
+
+void CanvasItemMaterial::set_unshaded(bool p_unshaded) {
+
+ unshaded=p_unshaded;
+ VS::get_singleton()->canvas_item_material_set_unshaded(material,p_unshaded);
+}
+
+bool CanvasItemMaterial::is_unshaded() const{
+
+ return unshaded;
+}
+
+void CanvasItemMaterial::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
+ ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
+ ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
+ ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
+ ObjectTypeDB::bind_method(_MD("set_unshaded","unshaded"),&CanvasItemMaterial::set_unshaded);
+ ObjectTypeDB::bind_method(_MD("is_unshaded"),&CanvasItemMaterial::is_unshaded);
+
+}
+
+void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
+
+ String f = p_function.operator String();
+ if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) {
+
+ if (shader.is_valid()) {
+ List<PropertyInfo> pl;
+ shader->get_param_list(&pl);
+ for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
+ r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
+ }
+ }
+ }
+ Resource::get_argument_options(p_function,p_idx,r_options);
+}
+
+CanvasItemMaterial::CanvasItemMaterial() {
+
+ material=VS::get_singleton()->canvas_item_material_create();
+ unshaded=false;
+}
+
+CanvasItemMaterial::~CanvasItemMaterial(){
+
+ VS::get_singleton()->free(material);
+}
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////
+
+
+
bool CanvasItem::is_visible() const {
if (!is_inside_tree())
@@ -730,110 +915,94 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{
return behind;
}
-void CanvasItem::set_shader(const Ref<Shader>& p_shader) {
-
- ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
-
-#ifdef TOOLS_ENABLED
-
- if (shader.is_valid()) {
- shader->disconnect("changed",this,"_shader_changed");
- }
-#endif
- shader=p_shader;
-
-#ifdef TOOLS_ENABLED
+void CanvasItem::set_material(const Ref<CanvasItemMaterial>& p_material) {
- if (shader.is_valid()) {
- shader->connect("changed",this,"_shader_changed");
- }
-#endif
+ material=p_material;
RID rid;
- if (shader.is_valid())
- rid=shader->get_rid();
- VS::get_singleton()->canvas_item_set_shader(canvas_item,rid);
- _change_notify(); //properties for shader exposed
+ if (material.is_valid())
+ rid=material->get_rid();
+ VS::get_singleton()->canvas_item_set_material(canvas_item,rid);
+ _change_notify(); //properties for material exposed
}
-void CanvasItem::set_use_parent_shader(bool p_use_parent_shader) {
+void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
- use_parent_shader=p_use_parent_shader;
- VS::get_singleton()->canvas_item_set_use_parent_shader(canvas_item,p_use_parent_shader);
+ use_parent_material=p_use_parent_material;
+ VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item,p_use_parent_material);
}
-bool CanvasItem::get_use_parent_shader() const{
+bool CanvasItem::get_use_parent_material() const{
- return use_parent_shader;
+ return use_parent_material;
}
-Ref<Shader> CanvasItem::get_shader() const{
+Ref<CanvasItemMaterial> CanvasItem::get_material() const{
- return shader;
+ return material;
}
-void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) {
- VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value);
-}
+InputEvent CanvasItem::make_input_local(const InputEvent& p_event) const {
-Variant CanvasItem::get_shader_param(const StringName& p_param) const {
+ ERR_FAIL_COND_V(!is_inside_tree(),p_event);
- return VS::get_singleton()->canvas_item_get_shader_param(canvas_item,p_param);
-}
+ InputEvent ev = p_event;
-bool CanvasItem::_set(const StringName& p_name, const Variant& p_value) {
+ Matrix32 local_matrix = (get_canvas_transform() * get_global_transform()).affine_inverse();
- if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
- if (pr) {
- set_shader_param(pr,p_value);
- return true;
- }
- }
- return false;
-}
+ switch(ev.type) {
-bool CanvasItem::_get(const StringName& p_name,Variant &r_ret) const{
+ case InputEvent::MOUSE_BUTTON: {
- if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
- if (pr) {
- r_ret=get_shader_param(pr);
- return true;
- }
- }
- return false;
-
-}
-void CanvasItem::_get_property_list( List<PropertyInfo> *p_list) const{
-
- if (shader.is_valid()) {
- shader->get_param_list(p_list);
- }
-}
-
-#ifdef TOOLS_ENABLED
-void CanvasItem::_shader_changed() {
+ Vector2 g = local_matrix.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y));
+ Vector2 l = local_matrix.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y));
+ ev.mouse_button.x=l.x;
+ ev.mouse_button.y=l.y;
+ ev.mouse_button.global_x=g.x;
+ ev.mouse_button.global_y=g.y;
- _change_notify();
-}
-#endif
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ Vector2 g = local_matrix.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y));
+ Vector2 l = local_matrix.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y));
+ Vector2 r = local_matrix.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y));
+ Vector2 s = local_matrix.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y));
+ ev.mouse_motion.x=l.x;
+ ev.mouse_motion.y=l.y;
+ ev.mouse_motion.global_x=g.x;
+ ev.mouse_motion.global_y=g.y;
+ ev.mouse_motion.relative_x=r.x;
+ ev.mouse_motion.relative_y=r.y;
+ ev.mouse_motion.speed_x=s.x;
+ ev.mouse_motion.speed_y=s.y;
-void CanvasItem::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
- if (p_idx==0 && shader.is_valid() && (p_function.operator String()=="get_shader_param" || p_function.operator String()=="set_shader_param")) {
- List<PropertyInfo> pl;
- shader->get_param_list(&pl);
- for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
- r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
- }
+ Vector2 t = local_matrix.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y));
+ ev.screen_touch.x=t.x;
+ ev.screen_touch.y=t.y;
- return;
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+
+
+ Vector2 t = local_matrix.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y));
+ Vector2 r = local_matrix.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y));
+ Vector2 s = local_matrix.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y));
+ ev.screen_drag.x=t.x;
+ ev.screen_drag.y=t.y;
+ ev.screen_drag.relative_x=r.x;
+ ev.screen_drag.relative_y=r.y;
+ ev.screen_drag.speed_x=s.x;
+ ev.screen_drag.speed_y=s.y;
+ } break;
}
- Node::get_argument_options(p_function,p_idx,r_options);
+ return ev;
}
@@ -880,9 +1049,6 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top);
-#ifdef TOOLS_ENABLED
- ObjectTypeDB::bind_method(_MD("_shader_changed"),&CanvasItem::_shader_changed);
-#endif
//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0));
@@ -901,20 +1067,21 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
ObjectTypeDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform);
+ ObjectTypeDB::bind_method(_MD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas);
ObjectTypeDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform);
ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
+ ObjectTypeDB::bind_method(_MD("get_canvas_transform"),&CanvasItem::get_canvas_transform);
ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas);
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
//ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
- ObjectTypeDB::bind_method(_MD("set_shader","shader"),&CanvasItem::set_shader);
- ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader);
- ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader);
- ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader);
+ ObjectTypeDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material);
+ ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material);
- ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItem::set_shader_param);
- ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItem::get_shader_param);
+ ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material);
+ ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material);
+ ObjectTypeDB::bind_method(_MD("make_input_local","event"),&CanvasItem::make_input_local);
BIND_VMETHOD(MethodInfo("_draw"));
@@ -926,8 +1093,8 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"material/use_parent"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") );
//exporting these two things doesn't really make much sense i think
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
//ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
@@ -1004,7 +1171,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
block_transform_notify=false;
// viewport=NULL;
canvas_layer=NULL;
- use_parent_shader=false;
+ use_parent_material=false;
global_invalid=true;
light_mask=1;
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 2441d205ce..c43642a8ec 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -40,6 +40,41 @@ class Font;
class StyleBox;
+class CanvasItemMaterial : public Resource{
+
+ OBJ_TYPE(CanvasItemMaterial,Resource);
+ RID material;
+ Ref<Shader> shader;
+ bool unshaded;
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+ void _shader_changed();
+ static void _bind_methods();
+
+ void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
+
+public:
+
+ void set_shader(const Ref<Shader>& p_shader);
+ Ref<Shader> get_shader() const;
+
+ void set_shader_param(const StringName& p_param,const Variant& p_value);
+ Variant get_shader_param(const StringName& p_param) const;
+
+ void set_unshaded(bool p_unshaded);
+ bool is_unshaded() const;
+
+ virtual RID get_rid() const;
+ CanvasItemMaterial();
+ ~CanvasItemMaterial();
+};
+
+
class CanvasItem : public Node {
OBJ_TYPE( CanvasItem, Node );
@@ -81,9 +116,9 @@ private:
bool drawing;
bool block_transform_notify;
bool behind;
- bool use_parent_shader;
+ bool use_parent_material;
- Ref<Shader> shader;
+ Ref<CanvasItemMaterial> material;
mutable Matrix32 global_transform;
mutable bool global_invalid;
@@ -104,9 +139,6 @@ private:
void _queue_sort_children();
void _sort_children();
-#ifdef TOOLS_ENABLED
- void _shader_changed();
-#endif
void _notify_transform(CanvasItem *p_node);
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
@@ -114,11 +146,6 @@ private:
protected:
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
-
_FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); }
void item_rect_changed();
@@ -216,16 +243,13 @@ public:
RID get_canvas() const;
Ref<World2D> get_world_2d() const;
- void set_shader(const Ref<Shader>& p_shader);
- Ref<Shader> get_shader() const;
+ void set_material(const Ref<CanvasItemMaterial>& p_material);
+ Ref<CanvasItemMaterial> get_material() const;
- void set_use_parent_shader(bool p_use_parent_shader);
- bool get_use_parent_shader() const;
+ void set_use_parent_material(bool p_use_parent_material);
+ bool get_use_parent_material() const;
- void set_shader_param(const StringName& p_param,const Variant& p_value);
- Variant get_shader_param(const StringName& p_param) const;
-
- void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
+ InputEvent make_input_local(const InputEvent& pevent) const;
CanvasItem();
~CanvasItem();
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 3b859d9366..a883fee103 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -28,6 +28,7 @@
/*************************************************************************/
#include "collision_object_2d.h"
#include "servers/physics_2d_server.h"
+#include "scene/scene_string_names.h"
void CollisionObject2D::_update_shapes_from_children() {
@@ -58,9 +59,15 @@ void CollisionObject2D::_notification(int p_what) {
} else
Physics2DServer::get_singleton()->body_set_space(rid,space);
+ _update_pickable();
+
//get space
}
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+
+ _update_pickable();
+ } break;
case NOTIFICATION_TRANSFORM_CHANGED: {
if (area)
@@ -166,6 +173,57 @@ void CollisionObject2D::_get_property_list( List<PropertyInfo> *p_list) const {
}
}
+
+void CollisionObject2D::set_pickable(bool p_enabled) {
+
+ if (pickable==p_enabled)
+ return;
+
+ pickable=p_enabled;
+ _update_pickable();
+}
+
+bool CollisionObject2D::is_pickable() const {
+
+ return pickable;
+}
+
+void CollisionObject2D::_input_event(Node *p_viewport, const InputEvent& p_input_event, int p_shape) {
+
+ if (get_script_instance()) {
+ get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_viewport,p_input_event,p_shape);
+ }
+ emit_signal(SceneStringNames::get_singleton()->input_event,p_viewport,p_input_event,p_shape);
+}
+
+void CollisionObject2D::_mouse_enter() {
+
+ if (get_script_instance()) {
+ get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter);
+ }
+ emit_signal(SceneStringNames::get_singleton()->mouse_enter);
+}
+
+
+void CollisionObject2D::_mouse_exit() {
+
+ if (get_script_instance()) {
+ get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit);
+ }
+ emit_signal(SceneStringNames::get_singleton()->mouse_exit);
+
+}
+
+void CollisionObject2D::_update_pickable() {
+ if (!is_inside_tree())
+ return;
+ bool pickable = this->pickable && is_inside_tree() && is_visible();
+ if (area)
+ Physics2DServer::get_singleton()->area_set_pickable(rid,pickable);
+ else
+ Physics2DServer::get_singleton()->body_set_pickable(rid,pickable);
+}
+
void CollisionObject2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("add_shape","shape:Shape2D","transform"),&CollisionObject2D::add_shape,DEFVAL(Matrix32()));
@@ -180,6 +238,17 @@ void CollisionObject2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject2D::clear_shapes);
ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject2D::get_rid);
+ ObjectTypeDB::bind_method(_MD("set_pickable","enabled"),&CollisionObject2D::set_pickable);
+ ObjectTypeDB::bind_method(_MD("is_pickable"),&CollisionObject2D::is_pickable);
+
+ BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"viewport"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::INT,"shape_idx")));
+
+ ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::OBJECT,"viewport"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::INT,"shape_idx")));
+ ADD_SIGNAL( MethodInfo("mouse_enter"));
+ ADD_SIGNAL( MethodInfo("mouse_exit"));
+
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input/pickable"),_SCS("set_pickable"),_SCS("is_pickable"));
+
}
@@ -262,7 +331,9 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
rid=p_rid;
area=p_area;
+ pickable=true;
if (p_area) {
+
Physics2DServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
} else {
Physics2DServer::get_singleton()->body_attach_object_instance_ID(rid,get_instance_ID());
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index 4a529ce062..393973ce90 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -38,6 +38,7 @@ class CollisionObject2D : public Node2D {
bool area;
RID rid;
+ bool pickable;
struct ShapeData {
Matrix32 xform;
@@ -66,9 +67,17 @@ protected:
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list( List<PropertyInfo> *p_list) const;
static void _bind_methods();
+
+ void _update_pickable();
+friend class Viewport;
+ void _input_event(Node *p_viewport, const InputEvent& p_input_event, int p_shape);
+ void _mouse_enter();
+ void _mouse_exit();
+
public:
+
void add_shape(const Ref<Shape2D>& p_shape, const Matrix32& p_transform=Matrix32());
int get_shape_count() const;
void set_shape(int p_shape_idx, const Ref<Shape2D>& p_shape);
@@ -80,6 +89,9 @@ public:
void remove_shape(int p_shape_idx);
void clear_shapes();
+ void set_pickable(bool p_enabled);
+ bool is_pickable() const;
+
_FORCE_INLINE_ RID get_rid() const { return rid; }
CollisionObject2D();
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index cea8c06d3f..4abb7e5436 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -23,7 +23,7 @@ Rect2 Light2D::get_item_rect() const {
Size2i s;
- s = texture->get_size();
+ s = texture->get_size()*_scale;
Point2i ofs=texture_offset;
ofs-=s/2;
@@ -63,6 +63,8 @@ void Light2D::set_texture_offset( const Vector2& p_offset) {
texture_offset=p_offset;
VS::get_singleton()->canvas_light_set_texture_offset(canvas_light,texture_offset);
+ item_rect_changed();
+
}
Vector2 Light2D::get_texture_offset() const {
@@ -87,11 +89,27 @@ void Light2D::set_height( float p_height) {
VS::get_singleton()->canvas_light_set_height(canvas_light,height);
}
+
+
float Light2D::get_height() const {
return height;
}
+void Light2D::set_texture_scale( float p_scale) {
+
+ _scale=p_scale;
+ VS::get_singleton()->canvas_light_set_scale(canvas_light,_scale);
+ item_rect_changed();
+
+}
+
+
+float Light2D::get_texture_scale() const {
+
+ return _scale;
+}
+
void Light2D::set_z_range_min( int p_min_z) {
z_min=p_min_z;
@@ -148,6 +166,18 @@ int Light2D::get_item_mask() const {
return item_mask;
}
+void Light2D::set_item_shadow_mask( int p_mask) {
+
+ item_shadow_mask=p_mask;
+ VS::get_singleton()->canvas_light_set_item_shadow_mask(canvas_light,item_shadow_mask);
+
+}
+
+int Light2D::get_item_shadow_mask() const {
+
+ return item_shadow_mask;
+}
+
void Light2D::set_subtract_mode( bool p_enable ) {
subtract_mode=p_enable;
@@ -170,6 +200,29 @@ bool Light2D::is_shadow_enabled() const {
return shadow;
}
+void Light2D::set_shadow_buffer_size( int p_size ) {
+
+ shadow_buffer_size=p_size;
+ VS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light,shadow_buffer_size);
+}
+
+int Light2D::get_shadow_buffer_size() const {
+
+ return shadow_buffer_size;
+}
+
+void Light2D::set_shadow_esm_multiplier( float p_multiplier) {
+
+ shadow_esm_multiplier=p_multiplier;
+ VS::get_singleton()->canvas_light_set_shadow_esm_multiplier(canvas_light,p_multiplier);
+}
+
+float Light2D::get_shadow_esm_multiplier() const{
+
+ return shadow_esm_multiplier;
+}
+
+
void Light2D::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
@@ -207,6 +260,10 @@ void Light2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_height","height"),&Light2D::set_height);
ObjectTypeDB::bind_method(_MD("get_height"),&Light2D::get_height);
+ ObjectTypeDB::bind_method(_MD("set_texture_scale","texture_scale"),&Light2D::set_texture_scale);
+ ObjectTypeDB::bind_method(_MD("get_texture_scale"),&Light2D::get_texture_scale);
+
+
ObjectTypeDB::bind_method(_MD("set_z_range_min","z"),&Light2D::set_z_range_min);
ObjectTypeDB::bind_method(_MD("get_z_range_min"),&Light2D::get_z_range_min);
@@ -223,24 +280,37 @@ void Light2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_item_mask","item_mask"),&Light2D::set_item_mask);
ObjectTypeDB::bind_method(_MD("get_item_mask"),&Light2D::get_item_mask);
+ ObjectTypeDB::bind_method(_MD("set_item_shadow_mask","item_shadow_mask"),&Light2D::set_item_shadow_mask);
+ ObjectTypeDB::bind_method(_MD("get_item_shadow_mask"),&Light2D::get_item_shadow_mask);
+
ObjectTypeDB::bind_method(_MD("set_subtract_mode","enable"),&Light2D::set_subtract_mode);
ObjectTypeDB::bind_method(_MD("get_subtract_mode"),&Light2D::get_subtract_mode);
ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
+ ObjectTypeDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size);
+ ObjectTypeDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size);
+
+ ObjectTypeDB::bind_method(_MD("set_shadow_esm_multiplier","multiplier"),&Light2D::set_shadow_esm_multiplier);
+ ObjectTypeDB::bind_method(_MD("get_shadow_esm_multiplier"),&Light2D::get_shadow_esm_multiplier);
+
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),_SCS("set_height"),_SCS("get_height"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_shadow_mask"),_SCS("get_item_shadow_mask"));
}
@@ -252,12 +322,16 @@ Light2D::Light2D() {
shadow=false;
color=Color(1,1,1);
height=0;
+ _scale=1.0;
z_min=-1024;
z_max=1024;
layer_min=0;
layer_max=0;
item_mask=1;
+ item_shadow_mask=1;
subtract_mode=false;
+ shadow_buffer_size=2048;
+ shadow_esm_multiplier=80;
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index dbfd233d39..6cfb055fa9 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -12,11 +12,15 @@ private:
bool shadow;
Color color;
float height;
+ float _scale;
int z_min;
int z_max;
int layer_min;
int layer_max;
int item_mask;
+ int item_shadow_mask;
+ int shadow_buffer_size;
+ float shadow_esm_multiplier;
bool subtract_mode;
Ref<Texture> texture;
Vector2 texture_offset;
@@ -47,6 +51,9 @@ public:
void set_height( float p_height);
float get_height() const;
+ void set_texture_scale( float p_scale);
+ float get_texture_scale() const;
+
void set_z_range_min( int p_min_z);
int get_z_range_min() const;
@@ -62,12 +69,21 @@ public:
void set_item_mask( int p_mask);
int get_item_mask() const;
+ void set_item_shadow_mask( int p_mask);
+ int get_item_shadow_mask() const;
+
void set_subtract_mode( bool p_enable );
bool get_subtract_mode() const;
void set_shadow_enabled( bool p_enabled);
bool is_shadow_enabled() const;
+ void set_shadow_buffer_size( int p_size );
+ int get_shadow_buffer_size() const;
+
+ void set_shadow_esm_multiplier( float p_multiplier);
+ float get_shadow_esm_multiplier() const;
+
virtual Rect2 get_item_rect() const;
Light2D();
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
new file mode 100644
index 0000000000..6ebd499f71
--- /dev/null
+++ b/scene/2d/light_occluder_2d.cpp
@@ -0,0 +1,202 @@
+#include "light_occluder_2d.h"
+
+
+void OccluderPolygon2D::set_polygon(const DVector<Vector2>& p_polygon) {
+
+ polygon=p_polygon;
+ VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,p_polygon,closed);
+ emit_changed();
+}
+
+DVector<Vector2> OccluderPolygon2D::get_polygon() const{
+
+ return polygon;
+}
+
+void OccluderPolygon2D::set_closed(bool p_closed) {
+
+ if (closed==p_closed)
+ return;
+ closed=p_closed;
+ if (polygon.size())
+ VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed);
+ emit_changed();
+}
+
+bool OccluderPolygon2D::is_closed() const{
+
+ return closed;
+}
+
+void OccluderPolygon2D::set_cull_mode(CullMode p_mode){
+
+ cull=p_mode;
+ VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon,VS::CanvasOccluderPolygonCullMode(p_mode));
+}
+
+OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const{
+
+ return cull;
+}
+
+
+RID OccluderPolygon2D::get_rid() const {
+
+ return occ_polygon;
+}
+
+void OccluderPolygon2D::_bind_methods() {
+
+
+ ObjectTypeDB::bind_method(_MD("set_closed","closed"),&OccluderPolygon2D::set_closed);
+ ObjectTypeDB::bind_method(_MD("is_closed"),&OccluderPolygon2D::is_closed);
+
+ ObjectTypeDB::bind_method(_MD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode);
+ ObjectTypeDB::bind_method(_MD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode);
+
+ ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon);
+ ObjectTypeDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon);
+
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
+
+ BIND_CONSTANT(CULL_DISABLED);
+ BIND_CONSTANT(CULL_CLOCKWISE);
+ BIND_CONSTANT(CULL_COUNTER_CLOCKWISE);
+}
+
+
+OccluderPolygon2D::OccluderPolygon2D() {
+
+ occ_polygon=VS::get_singleton()->canvas_occluder_polygon_create();
+ closed=true;
+ cull=CULL_DISABLED;
+}
+
+OccluderPolygon2D::~OccluderPolygon2D() {
+
+ VS::get_singleton()->free(occ_polygon);
+}
+
+#ifdef DEBUG_ENABLED
+void LightOccluder2D::_poly_changed() {
+
+ update();
+}
+#endif
+
+
+void LightOccluder2D::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_CANVAS) {
+
+ VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,get_canvas());
+ VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
+
+ }
+ if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
+
+ VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ if (get_tree()->is_editor_hint()) {
+
+ if (occluder_polygon.is_valid()) {
+
+ DVector<Vector2> poly = occluder_polygon->get_polygon();
+
+ if (poly.size()) {
+ if (occluder_polygon->is_closed()) {
+ Vector<Color> color;
+ color.push_back(Color(0,0,0,0.6));
+ draw_polygon(Variant(poly),color);
+ } else {
+
+ int ps=poly.size();
+ DVector<Vector2>::Read r = poly.read();
+ for(int i=0;i<ps-1;i++) {
+
+ draw_line(r[i],r[i+1],Color(0,0,0,0.6),3);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if (p_what==NOTIFICATION_EXIT_CANVAS) {
+
+ VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,RID());
+ }
+
+
+}
+
+void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon) {
+
+#ifdef DEBUG_ENABLED
+ if (occluder_polygon.is_valid())
+ occluder_polygon->disconnect("changed",this,"_poly_changed");
+#endif
+ occluder_polygon=p_polygon;
+
+ if (occluder_polygon.is_valid())
+ VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,occluder_polygon->get_rid());
+ else
+ VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,RID());
+
+#ifdef DEBUG_ENABLED
+ if (occluder_polygon.is_valid())
+ occluder_polygon->connect("changed",this,"_poly_changed");
+ update();
+#endif
+
+}
+
+Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const {
+
+ return occluder_polygon;
+}
+
+void LightOccluder2D::set_occluder_light_mask(int p_mask) {
+
+ mask=p_mask;
+ VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder,mask);
+}
+
+int LightOccluder2D::get_occluder_light_mask() const{
+
+ return mask;
+}
+
+void LightOccluder2D::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon);
+ ObjectTypeDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon);
+
+ ObjectTypeDB::bind_method(_MD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask);
+ ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask);
+
+#ifdef DEBUG_ENABLED
+ ObjectTypeDB::bind_method("_poly_changed",&LightOccluder2D::_poly_changed);
+#endif
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),_SCS("set_occluder_polygon"),_SCS("get_occluder_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask"));
+}
+
+LightOccluder2D::LightOccluder2D() {
+
+ occluder=VS::get_singleton()->canvas_light_occluder_create();
+ mask=1;
+}
+
+LightOccluder2D::~LightOccluder2D() {
+
+ VS::get_singleton()->free(occluder);
+}
+
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
new file mode 100644
index 0000000000..0343e3697e
--- /dev/null
+++ b/scene/2d/light_occluder_2d.h
@@ -0,0 +1,73 @@
+#ifndef LIGHTOCCLUDER2D_H
+#define LIGHTOCCLUDER2D_H
+
+#include "scene/2d/node_2d.h"
+
+class OccluderPolygon2D : public Resource {
+
+ OBJ_TYPE(OccluderPolygon2D,Resource);
+public:
+
+ enum CullMode {
+ CULL_DISABLED,
+ CULL_CLOCKWISE,
+ CULL_COUNTER_CLOCKWISE
+ };
+private:
+
+
+ RID occ_polygon;
+ DVector<Vector2> polygon;
+ bool closed;
+ CullMode cull;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ void set_polygon(const DVector<Vector2>& p_polygon);
+ DVector<Vector2> get_polygon() const;
+
+ void set_closed(bool p_closed);
+ bool is_closed() const;
+
+ void set_cull_mode(CullMode p_mode);
+ CullMode get_cull_mode() const;
+
+ virtual RID get_rid() const;
+ OccluderPolygon2D();
+ ~OccluderPolygon2D();
+
+};
+
+VARIANT_ENUM_CAST(OccluderPolygon2D::CullMode);
+
+class LightOccluder2D : public Node2D {
+ OBJ_TYPE(LightOccluder2D,Node2D);
+
+ RID occluder;
+ bool enabled;
+ int mask;
+ Ref<OccluderPolygon2D> occluder_polygon;
+
+#ifdef DEBUG_ENABLED
+ void _poly_changed();
+#endif
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon);
+ Ref<OccluderPolygon2D> get_occluder_polygon() const;
+
+ void set_occluder_light_mask(int p_mask);
+ int get_occluder_light_mask() const;
+
+ LightOccluder2D();
+ ~LightOccluder2D();
+};
+
+#endif // LIGHTOCCLUDER2D_H
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 36b6b220b3..0b098f0cad 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -65,7 +65,7 @@ void Node2D::edit_set_state(const Variant& p_state) {
pos = state[0];
angle = state[1];
- scale = state[2];
+ _scale = state[2];
_update_transform();
_change_notify("transform/rot");
_change_notify("transform/scale");
@@ -93,11 +93,11 @@ void Node2D::edit_set_rect(const Rect2& p_edit_rect) {
Point2 new_pos = p_edit_rect.pos + p_edit_rect.size*zero_offset;//p_edit_rect.pos - r.pos;
Matrix32 postxf;
- postxf.set_rotation_and_scale(angle,scale);
+ postxf.set_rotation_and_scale(angle,_scale);
new_pos = postxf.xform(new_pos);
pos+=new_pos;
- scale*=new_scale;
+ _scale*=new_scale;
_update_transform();
_change_notify("transform/scale");
@@ -118,14 +118,14 @@ void Node2D::_update_xform_values() {
pos=_mat.elements[2];
angle=_mat.get_rotation();
- scale=_mat.get_scale();
+ _scale=_mat.get_scale();
_xform_dirty=false;
}
void Node2D::_update_transform() {
Matrix32 mat(angle,pos);
- _mat.set_rotation_and_scale(angle,scale);
+ _mat.set_rotation_and_scale(angle,_scale);
_mat.elements[2]=pos;
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),_mat);
@@ -161,11 +161,11 @@ void Node2D::set_scale(const Size2& p_scale) {
if (_xform_dirty)
((Node2D*)this)->_update_xform_values();
- scale=p_scale;
- if (scale.x==0)
- scale.x=CMP_EPSILON;
- if (scale.y==0)
- scale.y=CMP_EPSILON;
+ _scale=p_scale;
+ if (_scale.x==0)
+ _scale.x=CMP_EPSILON;
+ if (_scale.y==0)
+ _scale.y=CMP_EPSILON;
_update_transform();
_change_notify("transform/scale");
@@ -187,7 +187,7 @@ Size2 Node2D::get_scale() const {
if (_xform_dirty)
((Node2D*)this)->_update_xform_values();
- return scale;
+ return _scale;
}
void Node2D::_set_rotd(float p_angle) {
@@ -224,11 +224,27 @@ Rect2 Node2D::get_item_rect() const {
return Rect2(Point2(-32,-32),Size2(64,64));
}
-void Node2D::rotate(float p_degrees) {
+void Node2D::rotate(float p_radians) {
- set_rot( get_rot() + p_degrees);
+ set_rot( get_rot() + p_radians);
}
+void Node2D::translate(const Vector2& p_amount) {
+
+ set_pos( get_pos() + p_amount );
+}
+
+void Node2D::global_translate(const Vector2& p_amount) {
+
+ set_global_pos( get_global_pos() + p_amount );
+}
+
+void Node2D::scale(const Vector2& p_amount) {
+
+ set_scale( get_scale() * p_amount );
+}
+
+
void Node2D::move_x(float p_delta,bool p_scaled){
Matrix32 t = get_transform();
@@ -345,9 +361,12 @@ void Node2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_rot"),&Node2D::get_rot);
ObjectTypeDB::bind_method(_MD("get_scale"),&Node2D::get_scale);
- ObjectTypeDB::bind_method(_MD("rotate","degrees"),&Node2D::rotate);
+ ObjectTypeDB::bind_method(_MD("rotate","radians"),&Node2D::rotate);
ObjectTypeDB::bind_method(_MD("move_local_x","delta","scaled"),&Node2D::move_x,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("move_local_y","delta","scaled"),&Node2D::move_y,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("translate","offset"),&Node2D::translate);
+ ObjectTypeDB::bind_method(_MD("global_translate","offset"),&Node2D::global_translate);
+ ObjectTypeDB::bind_method(_MD("scale","ratio"),&Node2D::scale);
ObjectTypeDB::bind_method(_MD("set_global_pos","pos"),&Node2D::set_global_pos);
ObjectTypeDB::bind_method(_MD("get_global_pos"),&Node2D::get_global_pos);
@@ -379,7 +398,7 @@ Node2D::Node2D() {
angle=0;
- scale=Vector2(1,1);
+ _scale=Vector2(1,1);
_xform_dirty=false;
z=0;
z_relative=true;
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 7b059008c2..39a1061195 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -37,7 +37,7 @@ class Node2D : public CanvasItem {
Point2 pos;
float angle;
- Size2 scale;
+ Size2 _scale;
int z;
bool z_relative;
@@ -72,9 +72,12 @@ public:
void set_rot(float p_angle);
void set_scale(const Size2& p_scale);
- void rotate(float p_degrees);
+ void rotate(float p_radians);
void move_x(float p_delta,bool p_scaled=false);
void move_y(float p_delta,bool p_scaled=false);
+ void translate(const Vector2& p_amount);
+ void global_translate(const Vector2& p_amount);
+ void scale(const Vector2& p_amount);
Point2 get_pos() const;
float get_rot() const;
@@ -96,6 +99,7 @@ public:
Matrix32 get_relative_transform(const Node *p_parent) const;
+
Matrix32 get_transform() const;
Node2D();
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index 6e2cf5954b..c9dd92ff3d 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -1077,13 +1077,18 @@ void Particles2D::_bind_methods() {
BIND_CONSTANT( PARAM_SPREAD );
BIND_CONSTANT( PARAM_LINEAR_VELOCITY );
BIND_CONSTANT( PARAM_SPIN_VELOCITY );
+ BIND_CONSTANT( PARAM_ORBIT_VELOCITY );
BIND_CONSTANT( PARAM_GRAVITY_DIRECTION );
BIND_CONSTANT( PARAM_GRAVITY_STRENGTH );
BIND_CONSTANT( PARAM_RADIAL_ACCEL );
BIND_CONSTANT( PARAM_TANGENTIAL_ACCEL );
+ BIND_CONSTANT( PARAM_DAMPING );
+ BIND_CONSTANT( PARAM_INITIAL_ANGLE );
BIND_CONSTANT( PARAM_INITIAL_SIZE );
BIND_CONSTANT( PARAM_FINAL_SIZE );
BIND_CONSTANT( PARAM_HUE_VARIATION );
+ BIND_CONSTANT( PARAM_ANIM_SPEED_SCALE );
+ BIND_CONSTANT( PARAM_ANIM_INITIAL_POS );
BIND_CONSTANT( PARAM_MAX );
BIND_CONSTANT( MAX_COLOR_PHASES );
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 6f18325212..22dd0f01d0 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -98,6 +98,7 @@ PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject
mask=1;
set_one_way_collision_max_depth(0);
+ set_pickable(false);
}
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 75e7957cb8..2b88ee5dba 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -30,12 +30,32 @@
#include "io/marshalls.h"
#include "servers/physics_2d_server.h"
#include "method_bind_ext.inc"
+
+int TileMap::_get_quadrant_size() const {
+
+ if (y_sort_mode)
+ return 1;
+ else
+ return quadrant_size;
+}
+
void TileMap::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_ENTER_TREE: {
+ Node2D *c=this;
+ while(c) {
+
+ navigation=c->cast_to<Navigation2D>();
+ if (navigation) {
+ break;
+ }
+
+ c=c->get_parent()->cast_to<Node2D>();
+ }
+
pending_update=true;
_update_dirty_quadrants();
RID space = get_world_2d()->get_space();
@@ -47,6 +67,25 @@ void TileMap::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
_update_quadrant_space(RID());
+ for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
+
+ Quadrant &q=E->get();
+ if (navigation) {
+ for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) {
+
+ navigation->navpoly_remove(E->get().id);
+ }
+ q.navpoly_ids.clear();
+ }
+
+ for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) {
+ VS::get_singleton()->free(E->get().id);
+ }
+ q.occluder_instances.clear();
+ }
+
+ navigation=NULL;
+
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -74,6 +113,10 @@ void TileMap::_update_quadrant_transform() {
Matrix32 global_transform = get_global_transform();
+ Matrix32 nav_rel;
+ if (navigation)
+ nav_rel = get_relative_transform(navigation);
+
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
Quadrant &q=E->get();
@@ -81,6 +124,17 @@ void TileMap::_update_quadrant_transform() {
xform.set_origin( q.pos );
xform = global_transform * xform;
Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
+
+ if (navigation) {
+ for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) {
+
+ navigation->navpoly_set_transform(E->get().id,nav_rel * E->get().xform);
+ }
+ }
+
+ for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) {
+ VS::get_singleton()->canvas_light_occluder_set_transform(E->get().id,global_transform * E->get().xform);
+ }
}
}
@@ -161,6 +215,34 @@ bool TileMap::get_center_y() const {
return center_y;
}
+void TileMap::_fix_cell_transform(Matrix32& xform,const Cell& p_cell, const Vector2& p_offset, const Size2 &p_sc) {
+
+ Size2 s=p_sc;
+ Vector2 offset = p_offset;
+
+ if (p_cell.transpose) {
+ SWAP(xform.elements[0].x, xform.elements[0].y);
+ SWAP(xform.elements[1].x, xform.elements[1].y);
+ SWAP(offset.x, offset.y);
+ SWAP(s.x, s.y);
+ }
+ if (p_cell.flip_h) {
+ xform.elements[0].x=-xform.elements[0].x;
+ xform.elements[1].x=-xform.elements[1].x;
+ if (tile_origin==TILE_ORIGIN_TOP_LEFT)
+ offset.x=s.x-offset.x;
+ }
+ if (p_cell.flip_v) {
+ xform.elements[0].y=-xform.elements[0].y;
+ xform.elements[1].y=-xform.elements[1].y;
+ if (tile_origin==TILE_ORIGIN_TOP_LEFT)
+ offset.y=s.y-offset.y;
+ }
+ xform.elements[2].x+=offset.x;
+ xform.elements[2].y+=offset.y;
+
+}
+
void TileMap::_update_dirty_quadrants() {
if (!pending_update)
@@ -173,15 +255,42 @@ void TileMap::_update_dirty_quadrants() {
VisualServer *vs = VisualServer::get_singleton();
Physics2DServer *ps = Physics2DServer::get_singleton();
Vector2 tofs = get_cell_draw_offset();
+ Vector2 tcenter = cell_size/2;
+ Matrix32 nav_rel;
+ if (navigation)
+ nav_rel = get_relative_transform(navigation);
+
+ Vector2 qofs;
while (dirty_quadrant_list.first()) {
Quadrant &q = *dirty_quadrant_list.first()->self();
- vs->canvas_item_clear(q.canvas_item);
+ for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) {
+
+ vs->free(E->get());
+ }
+
+ q.canvas_items.clear();
+
ps->body_clear_shapes(q.body);
int shape_idx=0;
+ if (navigation) {
+ for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) {
+
+ navigation->navpoly_remove(E->get().id);
+ }
+ q.navpoly_ids.clear();
+ }
+
+ for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) {
+ VS::get_singleton()->free(E->get().id);
+ }
+ q.occluder_instances.clear();
+ Ref<CanvasItemMaterial> prev_material;
+ RID prev_canvas_item;
+
for(int i=0;i<q.cells.size();i++) {
Map<PosKey,Cell>::Element *E=tile_map.find( q.cells[i] );
@@ -192,11 +301,35 @@ void TileMap::_update_dirty_quadrants() {
Ref<Texture> tex = tile_set->tile_get_texture(c.id);
Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);
- Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs;
+ Vector2 wofs = _map_to_world(E->key().x, E->key().y);
+ Vector2 offset = wofs - q.pos + tofs;
if (!tex.is_valid())
continue;
+ Ref<CanvasItemMaterial> mat = tile_set->tile_get_material(c.id);
+
+ RID canvas_item;
+
+ if (prev_canvas_item==RID() || prev_material!=mat) {
+
+ canvas_item=vs->canvas_item_create();
+ if (mat.is_valid())
+ vs->canvas_item_set_material(canvas_item,mat->get_rid());
+ vs->canvas_item_set_parent( canvas_item, get_canvas_item() );
+ Matrix32 xform;
+ xform.set_origin( q.pos );
+ vs->canvas_item_set_transform( canvas_item, xform );
+ q.canvas_items.push_back(canvas_item);
+
+ prev_canvas_item=canvas_item;
+ prev_material=mat;
+
+ } else {
+ canvas_item=prev_canvas_item;
+ }
+
+
Rect2 r = tile_set->tile_get_region(c.id);
Size2 s = tex->get_size();
@@ -223,12 +356,32 @@ void TileMap::_update_dirty_quadrants() {
if (c.flip_v)
rect.size.y=-rect.size.y;
+ Vector2 center_ofs;
+
+ if (tile_origin==TILE_ORIGIN_TOP_LEFT) {
+ rect.pos+=tile_ofs;
+ } else if (tile_origin==TILE_ORIGIN_CENTER) {
+ rect.pos+=tcenter;
+
+ Vector2 center = (s/2) - tile_ofs;
+ center_ofs=tcenter-(s/2);
+
+ if (c.flip_h)
+ rect.pos.x-=s.x-center.x;
+ else
+ rect.pos.x-=center.x;
+
+ if (c.flip_v)
+ rect.pos.y-=s.y-center.y;
+ else
+ rect.pos.y-=center.y;
+ }
+
- rect.pos+=tile_ofs;
if (r==Rect2()) {
- tex->draw_rect(q.canvas_item,rect,false,Color(1,1,1),c.transpose);
+ tex->draw_rect(canvas_item,rect,false,Color(1,1,1),c.transpose);
} else {
- tex->draw_rect_region(q.canvas_item,rect,r,Color(1,1,1),c.transpose);
+ tex->draw_rect_region(canvas_item,rect,r,Color(1,1,1),c.transpose);
}
Vector< Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id);
@@ -242,32 +395,48 @@ void TileMap::_update_dirty_quadrants() {
Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id);
Matrix32 xform;
xform.set_origin(offset.floor());
- if (c.transpose) {
- SWAP(xform.elements[0].x, xform.elements[0].y);
- SWAP(xform.elements[1].x, xform.elements[1].y);
- SWAP(shape_ofs.x, shape_ofs.y);
- SWAP(s.x, s.y);
- }
- if (c.flip_h) {
- xform.elements[0].x=-xform.elements[0].x;
- xform.elements[1].x=-xform.elements[1].x;
- shape_ofs.x=s.x-shape_ofs.x;
- }
- if (c.flip_v) {
- xform.elements[0].y=-xform.elements[0].y;
- xform.elements[1].y=-xform.elements[1].y;
- shape_ofs.y=s.y-shape_ofs.y;
- }
- xform.elements[2].x+=shape_ofs.x;
- xform.elements[2].y+=shape_ofs.y;
-
+ _fix_cell_transform(xform,c,shape_ofs+center_ofs,s);
ps->body_add_shape(q.body,shape->get_rid(),xform);
ps->body_set_shape_metadata(q.body,shape_idx++,Vector2(E->key().x,E->key().y));
}
}
+
+ if (navigation) {
+ Ref<NavigationPolygon> navpoly = tile_set->tile_get_navigation_polygon(c.id);
+ Vector2 npoly_ofs = tile_set->tile_get_navigation_polygon_offset(c.id);
+ Matrix32 xform;
+ xform.set_origin(offset.floor()+q.pos);
+ _fix_cell_transform(xform,c,npoly_ofs+center_ofs,s);
+
+ int pid = navigation->navpoly_create(navpoly,nav_rel * xform);
+
+ Quadrant::NavPoly np;
+ np.id=pid;
+ np.xform=xform;
+ q.navpoly_ids[E->key()]=np;
+ }
+
+
+ Ref<OccluderPolygon2D> occluder=tile_set->tile_get_light_occluder(c.id);
+ if (occluder.is_valid()) {
+
+ Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id);
+ Matrix32 xform;
+ xform.set_origin(offset.floor()+q.pos);
+ _fix_cell_transform(xform,c,occluder_ofs+center_ofs,s);
+
+ RID orid = VS::get_singleton()->canvas_light_occluder_create();
+ VS::get_singleton()->canvas_light_occluder_set_transform(orid,get_global_transform() * xform);
+ VS::get_singleton()->canvas_light_occluder_set_polygon(orid,occluder->get_rid());
+ VS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid,get_canvas());
+ Quadrant::Occluder oc;
+ oc.xform=xform;
+ oc.id=orid;
+ q.occluder_instances[E->key()]=oc;
+ }
}
dirty_quadrant_list.remove( dirty_quadrant_list.first() );
@@ -282,10 +451,10 @@ void TileMap::_update_dirty_quadrants() {
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
Quadrant &q=E->get();
- if (q.canvas_item.is_valid()) {
- VS::get_singleton()->canvas_item_raise(q.canvas_item);
- }
+ for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) {
+ VS::get_singleton()->canvas_item_raise(E->get());
+ }
}
quadrant_order_dirty=false;
@@ -308,10 +477,10 @@ void TileMap::_recompute_rect_cache() {
Rect2 r;
- r.pos=_map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size);
- r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size) );
- r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size+quadrant_size) );
- r.expand_to( _map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size+quadrant_size) );
+ r.pos=_map_to_world(E->key().x*_get_quadrant_size(), E->key().y*_get_quadrant_size());
+ r.expand_to( _map_to_world(E->key().x*_get_quadrant_size()+_get_quadrant_size(), E->key().y*_get_quadrant_size()) );
+ r.expand_to( _map_to_world(E->key().x*_get_quadrant_size()+_get_quadrant_size(), E->key().y*_get_quadrant_size()+_get_quadrant_size()) );
+ r.expand_to( _map_to_world(E->key().x*_get_quadrant_size(), E->key().y*_get_quadrant_size()+_get_quadrant_size()) );
if (E==quadrant_map.front())
r_total=r;
else
@@ -322,7 +491,7 @@ void TileMap::_recompute_rect_cache() {
if (r_total==Rect2()) {
rect_cache=Rect2(-10,-10,20,20);
} else {
- rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*quadrant_size);
+ rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*_get_quadrant_size());
}
item_rect_changed();
@@ -338,11 +507,13 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const
Matrix32 xform;
//xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size);
Quadrant q;
- q.pos = _map_to_world(p_qk.x*quadrant_size,p_qk.y*quadrant_size);
+ q.pos = _map_to_world(p_qk.x*_get_quadrant_size(),p_qk.y*_get_quadrant_size());
+ q.pos+=get_cell_draw_offset();
+ if (tile_origin==TILE_ORIGIN_CENTER)
+ q.pos+=cell_size/2;
+
xform.set_origin( q.pos );
- q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
- VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() );
- VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform );
+// q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
q.body=Physics2DServer::get_singleton()->body_create(use_kinematic?Physics2DServer::BODY_MODE_KINEMATIC:Physics2DServer::BODY_MODE_STATIC);
Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.body,get_instance_ID());
Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer);
@@ -366,10 +537,27 @@ void TileMap::_erase_quadrant(Map<PosKey,Quadrant>::Element *Q) {
Quadrant &q=Q->get();
Physics2DServer::get_singleton()->free(q.body);
- VisualServer::get_singleton()->free(q.canvas_item);
+ for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) {
+
+ VisualServer::get_singleton()->free(E->get());
+ }
+ q.canvas_items.clear();
if (q.dirty_list.in_list())
dirty_quadrant_list.remove(&q.dirty_list);
+ if (navigation) {
+ for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) {
+
+ navigation->navpoly_remove(E->get().id);
+ }
+ q.navpoly_ids.clear();
+ }
+
+ for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) {
+ VS::get_singleton()->free(E->get().id);
+ }
+ q.occluder_instances.clear();
+
quadrant_map.erase(Q);
rect_cache_dirty=true;
}
@@ -397,7 +585,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bo
if (!E && p_tile==INVALID_CELL)
return; //nothing to do
- PosKey qk(p_x/quadrant_size,p_y/quadrant_size);
+ PosKey qk(p_x/_get_quadrant_size(),p_y/_get_quadrant_size());
if (p_tile==INVALID_CELL) {
//erase existing
tile_map.erase(pk);
@@ -495,7 +683,7 @@ void TileMap::_recreate_quadrants() {
for (Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) {
- PosKey qk(E->key().x/quadrant_size,E->key().y/quadrant_size);
+ PosKey qk(E->key().x/_get_quadrant_size(),E->key().y/_get_quadrant_size());
Map<PosKey,Quadrant>::Element *Q=quadrant_map.find(qk);
if (!Q) {
@@ -511,6 +699,7 @@ void TileMap::_recreate_quadrants() {
}
+
void TileMap::_clear_quadrants() {
while (quadrant_map.size()) {
@@ -678,6 +867,20 @@ void TileMap::set_half_offset(HalfOffset p_half_offset) {
emit_signal("settings_changed");
}
+void TileMap::set_tile_origin(TileOrigin p_tile_origin) {
+
+ _clear_quadrants();
+ tile_origin=p_tile_origin;
+ _recreate_quadrants();
+ emit_signal("settings_changed");
+}
+
+TileMap::TileOrigin TileMap::get_tile_origin() const{
+
+ return tile_origin;
+}
+
+
Vector2 TileMap::get_cell_draw_offset() const {
switch(mode) {
@@ -804,6 +1007,21 @@ Vector2 TileMap::world_to_map(const Vector2& p_pos) const{
return ret.floor();
}
+void TileMap::set_y_sort_mode(bool p_enable) {
+
+ _clear_quadrants();
+ y_sort_mode=p_enable;
+ VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),y_sort_mode);
+ _recreate_quadrants();
+ emit_signal("settings_changed");
+
+}
+
+bool TileMap::is_y_sort_mode_enabled() const {
+
+ return y_sort_mode;
+}
+
void TileMap::_bind_methods() {
@@ -829,12 +1047,18 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size);
+ ObjectTypeDB::bind_method(_MD("set_tile_origin","origin"),&TileMap::set_tile_origin);
+ ObjectTypeDB::bind_method(_MD("get_tile_origin"),&TileMap::get_tile_origin);
+
ObjectTypeDB::bind_method(_MD("set_center_x","enable"),&TileMap::set_center_x);
ObjectTypeDB::bind_method(_MD("get_center_x"),&TileMap::get_center_x);
ObjectTypeDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y);
ObjectTypeDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y);
+ ObjectTypeDB::bind_method(_MD("set_y_sort_mode","enable"),&TileMap::set_y_sort_mode);
+ ObjectTypeDB::bind_method(_MD("is_y_sort_mode_enabled"),&TileMap::is_y_sort_mode_enabled);
+
ObjectTypeDB::bind_method(_MD("set_collision_use_kinematic","use_kinematic"),&TileMap::set_collision_use_kinematic);
ObjectTypeDB::bind_method(_MD("get_collision_use_kinematic"),&TileMap::get_collision_use_kinematic);
@@ -871,6 +1095,8 @@ void TileMap::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/tile_origin",PROPERTY_HINT_ENUM,"Top Left,Center"),_SCS("set_tile_origin"),_SCS("get_tile_origin"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"cell/y_sort"),_SCS("set_y_sort_mode"),_SCS("is_y_sort_mode_enabled"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision/use_kinematic",PROPERTY_HINT_NONE,""),_SCS("set_collision_use_kinematic"),_SCS("get_collision_use_kinematic"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce"));
@@ -886,6 +1112,8 @@ void TileMap::_bind_methods() {
BIND_CONSTANT( HALF_OFFSET_X );
BIND_CONSTANT( HALF_OFFSET_Y );
BIND_CONSTANT( HALF_OFFSET_DISABLED );
+ BIND_CONSTANT( TILE_ORIGIN_TOP_LEFT );
+ BIND_CONSTANT( TILE_ORIGIN_CENTER );
}
@@ -906,9 +1134,12 @@ TileMap::TileMap() {
mode=MODE_SQUARE;
half_offset=HALF_OFFSET_DISABLED;
use_kinematic=false;
+ navigation=NULL;
+ y_sort_mode=false;
fp_adjust=0.01;
fp_adjust=0.01;
+ tile_origin=TILE_ORIGIN_TOP_LEFT;
}
TileMap::~TileMap() {
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index fe1067fc1d..e02c4ee5bb 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -30,6 +30,7 @@
#define TILE_MAP_H
#include "scene/2d/node_2d.h"
+#include "scene/2d/navigation2d.h"
#include "scene/resources/tile_set.h"
#include "self_list.h"
#include "vset.h"
@@ -51,6 +52,12 @@ public:
HALF_OFFSET_DISABLED,
};
+ enum TileOrigin {
+ TILE_ORIGIN_TOP_LEFT,
+ TILE_ORIGIN_CENTER
+ };
+
+
private:
Ref<TileSet> tile_set;
@@ -61,6 +68,7 @@ private:
Matrix32 custom_transform;
HalfOffset half_offset;
bool use_kinematic;
+ Navigation2D *navigation;
union PosKey {
@@ -98,15 +106,29 @@ private:
struct Quadrant {
Vector2 pos;
- RID canvas_item;
+ List<RID> canvas_items;
RID body;
SelfList<Quadrant> dirty_list;
+ struct NavPoly {
+ int id;
+ Matrix32 xform;
+ };
+
+ struct Occluder {
+ RID id;
+ Matrix32 xform;
+ };
+
+
+ Map<PosKey,NavPoly> navpoly_ids;
+ Map<PosKey,Occluder> occluder_instances;
+
VSet<PosKey> cells;
- void operator=(const Quadrant& q) { pos=q.pos; canvas_item=q.canvas_item; body=q.body; cells=q.cells; }
- Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_item=q.canvas_item; body=q.body; cells=q.cells;}
+ void operator=(const Quadrant& q) { pos=q.pos; canvas_items=q.canvas_items; body=q.body; cells=q.cells; navpoly_ids=q.navpoly_ids; occluder_instances=q.occluder_instances; }
+ Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_items=q.canvas_items; body=q.body; cells=q.cells; occluder_instances=q.occluder_instances; navpoly_ids=q.navpoly_ids;}
Quadrant() : dirty_list(this) {}
};
@@ -119,11 +141,14 @@ private:
Rect2 rect_cache;
bool rect_cache_dirty;
bool quadrant_order_dirty;
+ bool y_sort_mode;
float fp_adjust;
float friction;
float bounce;
uint32_t collision_layer;
+ TileOrigin tile_origin;
+ void _fix_cell_transform(Matrix32& xform, const Cell& p_cell, const Vector2 &p_offset, const Size2 &p_sc);
Map<PosKey,Quadrant>::Element *_create_quadrant(const PosKey& p_qk);
void _erase_quadrant(Map<PosKey,Quadrant>::Element *Q);
@@ -135,6 +160,9 @@ private:
void _update_quadrant_transform();
void _recompute_rect_cache();
+ _FORCE_INLINE_ int _get_quadrant_size() const;
+
+
void _set_tile_data(const DVector<int>& p_data);
DVector<int> _get_tile_data() const;
@@ -195,6 +223,9 @@ public:
void set_half_offset(HalfOffset p_half_offset);
HalfOffset get_half_offset() const;
+ void set_tile_origin(TileOrigin p_tile_origin);
+ TileOrigin get_tile_origin() const;
+
void set_custom_transform(const Matrix32& p_xform);
Matrix32 get_custom_transform() const;
@@ -204,6 +235,9 @@ public:
Vector2 map_to_world(const Vector2& p_pos, bool p_ignore_ofs=false) const;
Vector2 world_to_map(const Vector2& p_pos) const;
+ void set_y_sort_mode(bool p_enable);
+ bool is_y_sort_mode_enabled() const;
+
void clear();
TileMap();
@@ -212,5 +246,6 @@ public:
VARIANT_ENUM_CAST(TileMap::Mode);
VARIANT_ENUM_CAST(TileMap::HalfOffset);
+VARIANT_ENUM_CAST(TileMap::TileOrigin);
#endif // TILE_MAP_H
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 22534eeb0e..cd3c788b65 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -32,6 +32,7 @@
#include "scene/2d/physics_body_2d.h"
#include "scene/animation/animation_player.h"
#include "scene/scene_string_names.h"
+#include "particles_2d.h"
void VisibilityNotifier2D::_enter_viewport(Viewport* p_viewport) {
@@ -188,6 +189,15 @@ void VisibilityEnabler2D::_find_nodes(Node* p_node) {
}
+ if (enabler[ENABLER_PAUSE_PARTICLES]) {
+
+ Particles2D *ps = p_node->cast_to<Particles2D>();
+ if (ps) {
+ add=true;
+ }
+
+ }
+
if (add) {
p_node->connect(SceneStringNames::get_singleton()->exit_tree,this,"_node_removed",varray(p_node),CONNECT_ONESHOT);
@@ -271,6 +281,15 @@ void VisibilityEnabler2D::_change_node_state(Node* p_node,bool p_enabled) {
}
}
+ {
+ Particles2D *ps=p_node->cast_to<Particles2D>();
+
+ if (ps) {
+
+ ps->set_emitting(p_enabled);
+ }
+ }
+
}
@@ -292,9 +311,11 @@ void VisibilityEnabler2D::_bind_methods(){
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_animations"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATIONS );
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/freeze_bodies"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_FREEZE_BODIES);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_particles"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_PARTICLES);
BIND_CONSTANT( ENABLER_FREEZE_BODIES );
BIND_CONSTANT( ENABLER_PAUSE_ANIMATIONS );
+ BIND_CONSTANT( ENABLER_PAUSE_PARTICLES );
BIND_CONSTANT( ENABLER_MAX);
}
@@ -320,3 +341,4 @@ VisibilityEnabler2D::VisibilityEnabler2D() {
}
+
diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h
index cdf52ecb27..621c470d5d 100644
--- a/scene/2d/visibility_notifier_2d.h
+++ b/scene/2d/visibility_notifier_2d.h
@@ -73,6 +73,7 @@ public:
enum Enabler {
ENABLER_PAUSE_ANIMATIONS,
ENABLER_FREEZE_BODIES,
+ ENABLER_PAUSE_PARTICLES,
ENABLER_MAX
};
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 95eafa0df4..db69182ca0 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -152,11 +152,11 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const {
case PROJECTION_PERSPECTIVE: {
- p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_NOEDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_NOEDITOR) );
if (keep_aspect==KEEP_WIDTH)
- p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
else
- p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
} break;
@@ -680,8 +680,6 @@ void Camera::_bind_methods() {
ObjectTypeDB::bind_method( _MD("get_projection"),&Camera::get_projection );
ObjectTypeDB::bind_method( _MD("set_visible_layers","mask"),&Camera::set_visible_layers );
ObjectTypeDB::bind_method( _MD("get_visible_layers"),&Camera::get_visible_layers );
- ObjectTypeDB::bind_method( _MD("look_at","target","up"),&Camera::look_at );
- ObjectTypeDB::bind_method( _MD("look_at_from_pos","pos","target","up"),&Camera::look_at_from_pos );
ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&Camera::set_environment);
ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment);
ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode);
@@ -752,22 +750,6 @@ Vector<Plane> Camera::get_frustum() const {
-void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) {
-
- Transform lookat;
- lookat.origin=get_camera_transform().origin;
- lookat=lookat.looking_at(p_target,p_up_normal);
- set_global_transform(lookat);
-}
-
-void Camera::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal) {
-
- Transform lookat;
- lookat.origin=p_pos;
- lookat=lookat.looking_at(p_target,p_up_normal);
- set_global_transform(lookat);
-
-}
void Camera::set_v_offset(float p_offset) {
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index 950688dfda..de03282021 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -139,8 +139,6 @@ public:
void set_keep_aspect_mode(KeepAspect p_aspect);
KeepAspect get_keep_aspect_mode() const;
- void look_at(const Vector3& p_target, const Vector3& p_up_normal);
- void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal);
void set_v_offset(float p_offset);
float get_v_offset() const;
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index a5b009823c..6e11855543 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -593,6 +593,97 @@ bool Spatial::_is_visible_() const {
return !is_hidden();
}
+void Spatial::rotate(const Vector3& p_normal,float p_radians) {
+
+ Transform t =get_transform();
+ t.basis.rotate(p_normal,p_radians);
+ set_transform(t);
+}
+
+void Spatial::rotate_x(float p_radians) {
+
+ Transform t =get_transform();
+ t.basis.rotate(Vector3(1,0,0),p_radians);
+ set_transform(t);
+
+}
+
+void Spatial::rotate_y(float p_radians){
+
+ Transform t =get_transform();
+ t.basis.rotate(Vector3(0,1,0),p_radians);
+ set_transform(t);
+
+}
+void Spatial::rotate_z(float p_radians){
+
+ Transform t =get_transform();
+ t.basis.rotate(Vector3(0,0,1),p_radians);
+ set_transform(t);
+
+}
+
+void Spatial::translate(const Vector3& p_offset){
+
+ Transform t =get_transform();
+ t.origin+=p_offset;
+ set_transform(t);
+
+}
+void Spatial::scale(const Vector3& p_ratio){
+
+ Transform t =get_transform();
+ t.basis.scale(p_ratio);
+ set_transform(t);
+
+}
+void Spatial::global_rotate(const Vector3& p_normal,float p_radians){
+
+ Matrix3 rotation(p_normal,p_radians);
+ Transform t = get_global_transform();
+ t.basis= rotation * t.basis;
+ set_global_transform(t);
+
+}
+void Spatial::global_translate(const Vector3& p_offset){
+ Transform t = get_global_transform();
+ t.origin+=p_offset;
+ set_global_transform(t);
+
+}
+
+void Spatial::orthonormalize() {
+
+ Transform t = get_transform();
+ t.orthonormalize();
+ set_transform(t);
+
+}
+
+void Spatial::set_identity() {
+
+ set_transform(Transform());
+
+}
+
+
+void Spatial::look_at(const Vector3& p_target, const Vector3& p_up_normal) {
+
+ Transform lookat;
+ lookat.origin=get_global_transform().origin;
+ lookat=lookat.looking_at(p_target,p_up_normal);
+ set_global_transform(lookat);
+}
+
+void Spatial::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal) {
+
+ Transform lookat;
+ lookat.origin=p_pos;
+ lookat=lookat.looking_at(p_target,p_up_normal);
+ set_global_transform(lookat);
+
+}
+
void Spatial::_bind_methods() {
@@ -633,6 +724,28 @@ void Spatial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_visible_"), &Spatial::_set_visible_);
ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_visible_);
+ void rotate(const Vector3& p_normal,float p_radians);
+ void rotate_x(float p_radians);
+ void rotate_y(float p_radians);
+ void rotate_z(float p_radians);
+ void translate(const Vector3& p_offset);
+ void scale(const Vector3& p_ratio);
+ void global_rotate(const Vector3& p_normal,float p_radians);
+ void global_translate(const Vector3& p_offset);
+
+ ObjectTypeDB::bind_method( _MD("rotate","normal","radians"),&Spatial::rotate );
+ ObjectTypeDB::bind_method( _MD("global_rotate","normal","radians"),&Spatial::global_rotate );
+ ObjectTypeDB::bind_method( _MD("rotate_x","radians"),&Spatial::rotate_x );
+ ObjectTypeDB::bind_method( _MD("rotate_y","radians"),&Spatial::rotate_y );
+ ObjectTypeDB::bind_method( _MD("rotate_z","radians"),&Spatial::rotate_z );
+ ObjectTypeDB::bind_method( _MD("translate","offset"),&Spatial::translate );
+ ObjectTypeDB::bind_method( _MD("global_translate","offset"),&Spatial::global_translate );
+ ObjectTypeDB::bind_method( _MD("orthonormalize"),&Spatial::orthonormalize );
+ ObjectTypeDB::bind_method( _MD("set_identity"),&Spatial::set_identity );
+
+ ObjectTypeDB::bind_method( _MD("look_at","target","up"),&Spatial::look_at );
+ ObjectTypeDB::bind_method( _MD("look_at_from_pos","pos","target","up"),&Spatial::look_at_from_pos );
+
BIND_CONSTANT( NOTIFICATION_TRANSFORM_CHANGED );
BIND_CONSTANT( NOTIFICATION_ENTER_WORLD );
BIND_CONSTANT( NOTIFICATION_EXIT_WORLD );
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 49ecf5779b..f2cde8f1e6 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -167,6 +167,21 @@ public:
Transform get_relative_transform(const Node *p_parent) const;
+ void rotate(const Vector3& p_normal,float p_radians);
+ void rotate_x(float p_radians);
+ void rotate_y(float p_radians);
+ void rotate_z(float p_radians);
+ void translate(const Vector3& p_offset);
+ void scale(const Vector3& p_ratio);
+ void global_rotate(const Vector3& p_normal,float p_radians);
+ void global_translate(const Vector3& p_offset);
+
+ void look_at(const Vector3& p_target, const Vector3& p_up_normal);
+ void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal);
+
+ void orthonormalize();
+ void set_identity();
+
void show();
void hide();
bool is_visible() const;
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index a82c69e67f..45c7fa912c 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -310,6 +310,17 @@ int GeometryInstance::get_baked_light_texture_id() const{
return baked_light_texture_id;
}
+void GeometryInstance::set_extra_cull_margin(float p_margin) {
+
+ ERR_FAIL_COND(p_margin<0);
+ extra_cull_margin=p_margin;
+ VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(),extra_cull_margin);
+}
+
+float GeometryInstance::get_extra_cull_margin() const{
+
+ return extra_cull_margin;
+}
void GeometryInstance::_bind_methods() {
@@ -328,6 +339,9 @@ void GeometryInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id","id"), &GeometryInstance::set_baked_light_texture_id);
ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id);
+ ObjectTypeDB::bind_method(_MD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin);
+ ObjectTypeDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
+
ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE);
@@ -336,6 +350,7 @@ void GeometryInstance::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/receive_shadows"), _SCS("set_flag"), _SCS("get_flag"),FLAG_RECEIVE_SHADOWS);
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_begin",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_begin"), _SCS("get_draw_range_begin"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_end",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_end"), _SCS("get_draw_range_end"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "geometry/extra_cull_margin",PROPERTY_HINT_RANGE,"0,16384,0"), _SCS("set_extra_cull_margin"), _SCS("get_extra_cull_margin"));
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard_y"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD_FIX_Y);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE);
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index e9fefe1ba0..e08acbe9a2 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -108,6 +108,7 @@ private:
void _find_baked_light();
BakedLightInstance *baked_light_instance;
int baked_light_texture_id;
+ float extra_cull_margin;
void _baked_light_changed();
void _update_visibility();
@@ -132,6 +133,9 @@ public:
void set_baked_light_texture_id(int p_id);
int get_baked_light_texture_id() const;
+ void set_extra_cull_margin(float p_margin);
+ float get_extra_cull_margin() const;
+
GeometryInstance();
};
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 0167687621..bbe15da1cc 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -279,12 +279,12 @@ void BaseButton::set_disabled(bool p_disabled) {
set_focus_mode(FOCUS_NONE);
else
set_focus_mode(FOCUS_ALL);
-};
+}
bool BaseButton::is_disabled() const {
return status.disabled;
-};
+}
void BaseButton::set_pressed(bool p_pressed) {
@@ -391,6 +391,7 @@ void BaseButton::_bind_methods() {
ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press"));
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
new file mode 100644
index 0000000000..309152ba8f
--- /dev/null
+++ b/scene/gui/check_box.cpp
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* check_button.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "check_box.h"
+
+#include "servers/visual_server.h"
+#include "button_group.h"
+
+
+void CheckBox::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ RID ci = get_canvas_item();
+
+ Ref<Texture> on=Control::get_icon(is_radio() ? "radio_checked" : "checked");
+ Ref<Texture> off=Control::get_icon(is_radio() ? "radio_unchecked" : "unchecked");
+
+ Vector2 ofs;
+ ofs.x = 0;
+ ofs.y = int((get_size().height - on->get_height())/2);
+
+ if (is_pressed())
+ on->draw(ci,ofs);
+ else
+ off->draw(ci,ofs);
+
+
+ }
+}
+
+bool CheckBox::is_radio()
+{
+ Node* parent = this;
+ do {
+ parent = parent->get_parent();
+ if (dynamic_cast< ButtonGroup* >(parent))
+ break;
+ } while (parent);
+
+ return (parent != 0);
+}
+
+CheckBox::CheckBox(const String &p_text):
+ Button(p_text)
+{
+ set_toggle_mode(true);
+ set_text_align(ALIGN_LEFT);
+
+}
+
+CheckBox::~CheckBox()
+{
+}
diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h
new file mode 100644
index 0000000000..171fd55351
--- /dev/null
+++ b/scene/gui/check_box.h
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* check_box.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 CHECK_BOX_H
+#define CHECK_BOX_H
+
+
+#include "scene/gui/button.h"
+/**
+@author Mariano Suligoy <marianognu.esyrpg@gmail.com>
+*/
+class CheckBox : public Button {
+
+ OBJ_TYPE( CheckBox, Button );
+
+
+protected:
+ void _notification(int p_what);
+
+ bool is_radio();
+
+
+public:
+
+ CheckBox(const String& p_text=String());
+ ~CheckBox();
+
+};
+
+#endif
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 193649c815..d944b804a5 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -352,6 +352,7 @@ void ColorPickerButton::set_color(const Color& p_color){
picker->set_color(p_color);
+ update();
}
Color ColorPickerButton::get_color() const{
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index a8070be91d..86f442fd8c 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -940,67 +940,67 @@ void Control::_window_input_event(InputEvent p_event) {
case InputEvent::MOUSE_BUTTON: {
- window->key_event_accepted=false;
+ window->key_event_accepted=false;
- Point2 mpos =(get_canvas_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y));
- if (p_event.mouse_button.pressed) {
+ Point2 mpos =(get_canvas_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y));
+ if (p_event.mouse_button.pressed) {
- Size2 pos = mpos;
- if (window->mouse_focus && p_event.mouse_button.button_index!=window->mouse_focus_button) {
+ Size2 pos = mpos;
+ if (window->mouse_focus && p_event.mouse_button.button_index!=window->mouse_focus_button) {
- //do not steal mouse focus and stuff
+ //do not steal mouse focus and stuff
- } else {
+ } else {
- _window_sort_modal_stack();
- while (!window->modal_stack.empty()) {
+ _window_sort_modal_stack();
+ while (!window->modal_stack.empty()) {
- Control *top = window->modal_stack.back()->get();
- if (!top->has_point(top->get_global_transform().affine_inverse().xform(pos))) {
+ Control *top = window->modal_stack.back()->get();
+ if (!top->has_point(top->get_global_transform().affine_inverse().xform(pos))) {
- if (top->data.modal_exclusive) {
- //cancel event, sorry, modal exclusive EATS UP ALL
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
- get_tree()->set_input_as_handled();
- return; // no one gets the event if exclusive NO ONE
- }
+ if (top->data.modal_exclusive) {
+ //cancel event, sorry, modal exclusive EATS UP ALL
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
+ get_tree()->set_input_as_handled();
+ return; // no one gets the event if exclusive NO ONE
+ }
- top->notification(NOTIFICATION_MODAL_CLOSE);
- top->_modal_stack_remove();
- top->hide();
- } else {
- break;
+ top->notification(NOTIFICATION_MODAL_CLOSE);
+ top->_modal_stack_remove();
+ top->hide();
+ } else {
+ break;
+ }
}
- }
- Matrix32 parent_xform;
+ Matrix32 parent_xform;
- if (data.parent_canvas_item)
- parent_xform=data.parent_canvas_item->get_global_transform();
+ if (data.parent_canvas_item)
+ parent_xform=data.parent_canvas_item->get_global_transform();
- window->mouse_focus = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform);
- //print_line("has mf "+itos(window->mouse_focus!=NULL));
- window->mouse_focus_button=p_event.mouse_button.button_index;
+ window->mouse_focus = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform);
+ //print_line("has mf "+itos(window->mouse_focus!=NULL));
+ window->mouse_focus_button=p_event.mouse_button.button_index;
- if (!window->mouse_focus) {
- break;
- }
+ if (!window->mouse_focus) {
+ break;
+ }
- if (p_event.mouse_button.button_index==BUTTON_LEFT) {
- window->drag_accum=Vector2();
- window->drag_attempted=false;
- window->drag_data=Variant();
- }
+ if (p_event.mouse_button.button_index==BUTTON_LEFT) {
+ window->drag_accum=Vector2();
+ window->drag_attempted=false;
+ window->drag_data=Variant();
+ }
- }
+ }
p_event.mouse_button.global_x = pos.x;
p_event.mouse_button.global_y = pos.y;
@@ -1020,8 +1020,8 @@ void Control::_window_input_event(InputEvent p_event) {
/*if (bool(GLOBAL_DEF("debug/print_clicked_control",false))) {
- print_line(String(window->mouse_focus->get_path())+" - "+pos);
- }*/
+ print_line(String(window->mouse_focus->get_path())+" - "+pos);
+ }*/
#endif
if (window->mouse_focus->get_focus_mode()!=FOCUS_NONE && window->mouse_focus!=window->key_focus && p_event.mouse_button.button_index==BUTTON_LEFT) {
@@ -1033,10 +1033,12 @@ void Control::_window_input_event(InputEvent p_event) {
if (window->mouse_focus->can_process()) {
_window_call_input(window->mouse_focus,p_event);
}
-
+
get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
get_tree()->set_input_as_handled();
+ window->tooltip_popup->hide();
+
} else {
if (window->drag_preview && p_event.mouse_button.button_index==BUTTON_LEFT) {
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index fbcfdb69bb..47f862a58d 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -29,6 +29,8 @@
#include "file_dialog.h"
#include "scene/gui/label.h"
#include "print_string.h"
+#include "os/keyboard.h"
+#include "tools/editor/editor_settings.h"
FileDialog::GetIconFunc FileDialog::get_icon_func=NULL;
@@ -278,13 +280,20 @@ void FileDialog::update_file_list() {
List<String> dirs;
bool isdir;
+ bool ishidden;
+ bool show_hidden = EditorSettings::get_singleton()->get("file_dialog/show_hidden_files");
String item;
+
while ((item=dir_access->get_next(&isdir))!="") {
-
- if (!isdir)
- files.push_back(item);
- else
- dirs.push_back(item);
+
+ ishidden = dir_access->current_is_hidden();
+
+ if (show_hidden || !ishidden) {
+ if (!isdir)
+ files.push_back(item);
+ else
+ dirs.push_back(item);
+ }
}
dirs.sort_custom<NoCaseComparator>();
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index d2e1e7f0b9..892e4c9bc7 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -72,6 +72,7 @@ void Label::_notification(int p_what) {
if (clip && !autowrap)
VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(),true);
+
if (word_cache_dirty)
regenerate_word_cache();
@@ -87,7 +88,8 @@ void Label::_notification(int p_what) {
bool use_outlinde = get_constant("shadow_as_outline");
Point2 shadow_ofs(get_constant("shadow_offset_x"),get_constant("shadow_offset_y"));
-
+ VisualServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(),font.is_valid() && font->is_distance_field_hint());
+
int font_h = font->get_height();
int line_from=(int)get_val(); // + p_exposed.pos.y / font_h;
int lines_visible = size.y/font_h;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 8855627bb4..b26b55f076 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -498,7 +498,29 @@ void TextEdit::_notification(int p_what) {
for(int j=from;j<text[i].length();j++) {
CharType cc = text[i][j];
- if (cc==c)
+ //ignore any brackets inside a string
+ if (cc== '"' | cc == '\'') {
+ CharType quotation = cc;
+ do {
+ j++;
+ if (!(j<text[i].length())) {
+ break;
+ }
+ cc=text[i][j];
+ //skip over escaped quotation marks inside strings
+ if (cc=='\\') {
+ bool escaped = true;
+ while (j+1<text[i].length() && text[i][j+1]=='\\') {
+ escaped=!escaped;
+ j++;
+ }
+ if (escaped) {
+ j++;
+ continue;
+ }
+ }
+ } while (cc!= quotation);
+ } else if (cc==c)
stack++;
else if (cc==closec)
stack--;
@@ -547,7 +569,30 @@ void TextEdit::_notification(int p_what) {
for(int j=from;j>=0;j--) {
CharType cc = text[i][j];
- if (cc==c)
+ //ignore any brackets inside a string
+ if (cc== '"' | cc == '\'') {
+ CharType quotation = cc;
+ do {
+ j--;
+ if (!(j>=0)) {
+ break;
+ }
+ cc=text[i][j];
+ //skip over escaped quotation marks inside strings
+ if (cc==quotation) {
+ bool escaped = false;
+ while (j-1>=0 && text[i][j-1]=='\\') {
+ escaped=!escaped;
+ j--;
+ }
+ if (escaped) {
+ j--;
+ cc='\\';
+ continue;
+ }
+ }
+ } while (cc!= quotation);
+ } else if (cc==c)
stack++;
else if (cc==closec)
stack--;
@@ -1345,7 +1390,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
return;
}
- if (k.scancode==KEY_HOME) {
+ if (k.scancode==KEY_HOME && completion_index>0) {
completion_index=0;
completion_current=completion_options[completion_index];
@@ -1354,7 +1399,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
return;
}
- if (k.scancode==KEY_END) {
+ if (k.scancode==KEY_END && completion_index<completion_options.size()-1) {
completion_index=completion_options.size()-1;
completion_current=completion_options[completion_index];
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 02e009866f..ee400ae6d5 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -30,7 +30,7 @@
#include "os/os.h"
#include "scene/3d/spatial.h"
#include "os/input.h"
-
+#include "servers/physics_2d_server.h"
//#include "scene/3d/camera.h"
#include "servers/spatial_sound_server.h"
@@ -40,7 +40,7 @@
#include "scene/3d/spatial_indexer.h"
#include "scene/3d/collision_object.h"
-
+#include "scene/2d/collision_object_2d.h"
int RenderTargetTexture::get_width() const {
@@ -104,8 +104,10 @@ void Viewport::_update_stretch_transform() {
stretch_transform.scale(scale);
stretch_transform.elements[2]=size_override_margin*scale;
+
} else {
+
stretch_transform=Matrix32();
}
@@ -355,11 +357,12 @@ void Viewport::_notification(int p_what) {
case NOTIFICATION_FIXED_PROCESS: {
if (physics_object_picking) {
-#ifndef _3D_DISABLED
+
Vector2 last_pos(1e20,1e20);
CollisionObject *last_object;
ObjectID last_id=0;
PhysicsDirectSpaceState::RayResult result;
+ Physics2DDirectSpaceState *ss2d=Physics2DServer::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
bool motion_tested=false;
@@ -392,6 +395,60 @@ void Viewport::_notification(int p_what) {
}
+ if (ss2d) {
+ //send to 2D
+
+
+ uint64_t frame = get_tree()->get_frame();
+
+ Vector2 point = get_canvas_transform().affine_inverse().xform(pos);
+ Physics2DDirectSpaceState::ShapeResult res[64];
+ int rc = ss2d->intersect_point(point,res,64,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
+ for(int i=0;i<rc;i++) {
+
+ if (res[i].collider) {
+ CollisionObject2D *co=res[i].collider->cast_to<CollisionObject2D>();
+ if (co) {
+
+ Map<ObjectID,uint64_t>::Element *E=physics_2d_mouseover.find(res[i].collider_id);
+ if (!E) {
+ E=physics_2d_mouseover.insert(res[i].collider_id,frame);
+ co->_mouse_enter();
+ } else {
+ E->get()=frame;
+ }
+
+ co->_input_event(this,ev,res[i].shape);
+ }
+ }
+ }
+
+ List<Map<ObjectID,uint64_t>::Element*> to_erase;
+
+ for (Map<ObjectID,uint64_t>::Element*E=physics_2d_mouseover.front();E;E=E->next()) {
+ if (E->get()!=frame) {
+ Object *o=ObjectDB::get_instance(E->key());
+ if (o) {
+
+ CollisionObject2D *co=o->cast_to<CollisionObject2D>();
+ if (co) {
+ co->_mouse_exit();
+ }
+ }
+ to_erase.push_back(E);
+ }
+ }
+
+ while(to_erase.size()) {
+ physics_2d_mouseover.erase(to_erase.front()->get());
+ to_erase.pop_front();
+ }
+
+ }
+
+
+
+#ifndef _3D_DISABLED
bool captured=false;
if (physics_object_capture!=0) {
@@ -499,9 +556,9 @@ void Viewport::_notification(int p_what) {
_test_new_mouseover(new_collider);
}
-
- }
#endif
+ }
+
}
} break;
@@ -1021,8 +1078,9 @@ Matrix32 Viewport::_get_input_pre_xform() const {
ERR_FAIL_COND_V(to_screen_rect.size.x==0,pre_xf);
ERR_FAIL_COND_V(to_screen_rect.size.y==0,pre_xf);
- pre_xf.scale(rect.size/to_screen_rect.size);
+
pre_xf.elements[2]=-to_screen_rect.pos;
+ pre_xf.scale(rect.size/to_screen_rect.size);
} else {
pre_xf.elements[2]=-rect.pos;
@@ -1086,6 +1144,7 @@ void Viewport::_make_input_local(InputEvent& ev) {
} break;
}
+
}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index d2a22401bd..14f4f68217 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -124,6 +124,7 @@ friend class RenderTargetTexture;
ObjectID physics_object_over;
Vector2 physics_last_mousepos;
void _test_new_mouseover(ObjectID new_collider);
+ Map<ObjectID,uint64_t> physics_2d_mouseover;
void _update_rect();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index ff525203bf..afadbf0170 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -53,6 +53,7 @@
#include "scene/gui/color_picker.h"
#include "scene/gui/texture_frame.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/panel_container.h"
@@ -76,15 +77,18 @@
#include "scene/gui/reference_frame.h"
#include "scene/gui/graph_node.h"
#include "scene/gui/graph_edit.h"
+#include "scene/gui/tool_button.h"
#include "scene/resources/video_stream.h"
#include "scene/2d/particles_2d.h"
#include "scene/2d/path_2d.h"
#include "scene/2d/light_2d.h"
+#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/canvas_item.h"
#include "scene/2d/sprite.h"
#include "scene/2d/animated_sprite.h"
#include "scene/2d/polygon_2d.h"
+#include "scene/2d/back_buffer_copy.h"
#include "scene/2d/visibility_notifier_2d.h"
@@ -287,7 +291,9 @@ void register_scene_types() {
ObjectTypeDB::register_type<Popup>();
ObjectTypeDB::register_type<PopupPanel>();
ObjectTypeDB::register_type<MenuButton>();
+ ObjectTypeDB::register_type<CheckBox>();
ObjectTypeDB::register_type<CheckButton>();
+ ObjectTypeDB::register_type<ToolButton>();
ObjectTypeDB::register_type<Panel>();
ObjectTypeDB::register_type<Range>();
@@ -454,6 +460,7 @@ void register_scene_types() {
//ObjectTypeDB::set_type_enabled("BodyVolumeCylinder",false);
//ObjectTypeDB::set_type_enabled("BodyVolumeConvexPolygon",false);
+ ObjectTypeDB::register_type<CanvasItemMaterial>();
ObjectTypeDB::register_virtual_type<CanvasItem>();
ObjectTypeDB::register_type<Node2D>();
ObjectTypeDB::register_type<Particles2D>();
@@ -476,7 +483,10 @@ void register_scene_types() {
ObjectTypeDB::register_type<VisibilityEnabler2D>();
ObjectTypeDB::register_type<Polygon2D>();
ObjectTypeDB::register_type<Light2D>();
+ ObjectTypeDB::register_type<LightOccluder2D>();
+ ObjectTypeDB::register_type<OccluderPolygon2D>();
ObjectTypeDB::register_type<YSort>();
+ ObjectTypeDB::register_type<BackBufferCopy>();
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false);
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 4d1e9896db..7d5981522e 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -300,6 +300,40 @@ void make_default_theme() {
t->set_constant("hseparation","MenuButton", 0 );
+ // CheckBox
+
+ Ref<StyleBox> cbx_empty = memnew( StyleBoxEmpty );
+ cbx_empty->set_default_margin(MARGIN_LEFT,22);
+ cbx_empty->set_default_margin(MARGIN_RIGHT,4);
+ cbx_empty->set_default_margin(MARGIN_TOP,4);
+ cbx_empty->set_default_margin(MARGIN_BOTTOM,5);
+ Ref<StyleBox> cbx_focus = focus;
+ cbx_focus->set_default_margin(MARGIN_LEFT,4);
+ cbx_focus->set_default_margin(MARGIN_RIGHT,22);
+ cbx_focus->set_default_margin(MARGIN_TOP,4);
+ cbx_focus->set_default_margin(MARGIN_BOTTOM,5);
+
+ t->set_stylebox("normal","CheckBox", cbx_empty );
+ t->set_stylebox("pressed","CheckBox", cbx_empty );
+ t->set_stylebox("disabled","CheckBox", cbx_empty );
+ t->set_stylebox("hover","CheckBox", cbx_empty );
+ t->set_stylebox("focus","CheckBox", cbx_focus );
+
+ t->set_icon("checked", "CheckBox", make_icon(checked_png));
+ t->set_icon("unchecked", "CheckBox", make_icon(unchecked_png));
+ t->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png));
+ t->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png));
+
+ t->set_font("font","CheckBox", default_font );
+
+ t->set_color("font_color","CheckBox", control_font_color );
+ t->set_color("font_color_pressed","CheckBox", control_font_color_pressed );
+ t->set_color("font_color_hover","CheckBox", control_font_color_hover );
+ t->set_color("font_color_disabled","CheckBox", control_font_color_disabled );
+
+ t->set_constant("hseparation","CheckBox",4);
+ t->set_constant("check_vadjust","CheckBox",0);
+
// CheckButton
@@ -308,7 +342,7 @@ void make_default_theme() {
cb_empty->set_default_margin(MARGIN_LEFT,6);
cb_empty->set_default_margin(MARGIN_RIGHT,70);
cb_empty->set_default_margin(MARGIN_TOP,4);
- cb_empty->set_default_margin(MARGIN_BOTTOM,4);
+ cb_empty->set_default_margin(MARGIN_BOTTOM,4);
t->set_stylebox("normal","CheckButton", cb_empty );
t->set_stylebox("pressed","CheckButton", cb_empty );
@@ -540,7 +574,7 @@ void make_default_theme() {
// Tree
Ref<StyleBoxTexture> tree_selected = make_stylebox( selection_png,4,4,4,4,8,0,8,0);
- Ref<StyleBoxTexture> tree_selected_oof = make_stylebox( selection_oof_png,4,4,4,4,8,0,8,0);
+ Ref<StyleBoxTexture> tree_selected_oof = make_stylebox( selection_oof_png,4,4,4,4,8,0,8,0);
t->set_stylebox("bg","Tree", make_stylebox( tree_bg_png,4,4,4,5) );
t->set_stylebox("bg_focus","Tree", focus );
diff --git a/scene/resources/default_theme/radio_checked.png b/scene/resources/default_theme/radio_checked.png
new file mode 100644
index 0000000000..ada8dde3c1
--- /dev/null
+++ b/scene/resources/default_theme/radio_checked.png
Binary files differ
diff --git a/scene/resources/default_theme/radio_unchecked.png b/scene/resources/default_theme/radio_unchecked.png
new file mode 100644
index 0000000000..018af99afd
--- /dev/null
+++ b/scene/resources/default_theme/radio_unchecked.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index e9a6d3dad6..78e210239d 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -264,6 +264,16 @@ static const unsigned char progress_fill_png[]={
};
+static const unsigned char radio_checked_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x3,0x1,0x4,0x19,0x36,0x83,0x13,0x8d,0xb2,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x1,0x9d,0x49,0x44,0x41,0x54,0x38,0xcb,0xad,0x93,0x31,0x6b,0xdb,0x50,0x14,0x85,0x3f,0x59,0x8a,0x21,0xbb,0x17,0xd1,0x37,0xa4,0xa4,0xb5,0x10,0xb5,0x3,0xfa,0x7,0x5d,0x3a,0x74,0xf2,0x56,0x39,0x64,0x4d,0x97,0x42,0x9b,0xce,0x6d,0x7e,0x44,0xe3,0x8e,0xf5,0x60,0x4,0xc5,0x22,0x9b,0x27,0x63,0xe8,0xea,0xc5,0x43,0x4d,0x48,0x40,0x7a,0xe9,0xd0,0xe0,0xd4,0x68,0x32,0x18,0x3c,0x8,0x64,0xc3,0xed,0x50,0x59,0x34,0x71,0xa7,0x3a,0x7,0xde,0x72,0xef,0x79,0x87,0x7b,0xde,0x3d,0xf,0xb6,0x84,0x71,0xbf,0xe0,0x38,0xce,0x23,0xe0,0x2d,0xf0,0x12,0xa8,0xe6,0xe5,0x6b,0xa0,0xf,0x7c,0xd6,0x5a,0x4f,0xff,0x29,0x60,0x99,0x16,0xfb,0x4f,0xf6,0x8f,0x81,0x56,0xb3,0x79,0xb4,0x7b,0x78,0xf8,0xa,0xc3,0xf8,0xd3,0x16,0x11,0xba,0xdd,0x73,0xc2,0xf0,0x6b,0xa,0xbc,0x9b,0x4c,0x26,0xed,0x34,0x4d,0xef,0xa,0x38,0x8e,0x73,0xbc,0xb7,0xf7,0xf8,0xcb,0xd9,0xd9,0xa7,0xe2,0xe2,0x7d,0x88,0x8,0x27,0x27,0xef,0xb9,0xb9,0xf9,0xf9,0x5a,0x6b,0xdd,0x2e,0x4,0xf2,0xb1,0x7f,0xf4,0x7a,0xbd,0x5d,0xc3,0x30,0xc8,0xb2,0x8c,0xf1,0x78,0x4c,0x14,0x45,0x0,0xb8,0xae,0x8b,0xe7,0x79,0x94,0xcb,0x65,0x44,0x84,0x46,0xa3,0x91,0x2,0x4f,0xb5,0xd6,0x53,0x13,0xa0,0x52,0xa9,0x7c,0x6c,0x36,0x8f,0x9e,0x1f,0x1c,0xd4,0xc8,0xb2,0x8c,0x4e,0xa7,0x43,0xab,0xd5,0x62,0x30,0x18,0x30,0x1c,0xe,0x19,0x8d,0x46,0xac,0x56,0x2b,0xea,0xf5,0x3a,0x96,0x65,0x21,0x52,0xda,0xb9,0xba,0xba,0x5c,0xce,0x66,0xb3,0x6f,0xeb,0xf1,0x2f,0xe2,0x38,0x16,0xad,0xb5,0x4,0x41,0x20,0x4a,0x29,0x1,0xee,0x1c,0xa5,0x94,0x4,0x41,0x20,0x5a,0x6b,0x89,0xe3,0x58,0x1c,0xc7,0xb9,0x0,0x28,0xe5,0xf6,0xaa,0x6b,0xdf,0x51,0x14,0x91,0x24,0xc9,0x86,0xff,0x24,0x49,0xa,0x4b,0x39,0xb7,0xfa,0xb7,0xc0,0x7f,0x63,0x2d,0x70,0x2d,0x22,0xc5,0x83,0xd9,0xb6,0xbd,0x41,0xb4,0x6d,0x1b,0xd7,0x75,0x8b,0x6d,0xe4,0xd9,0x28,0x4,0xfa,0xdd,0xee,0x39,0x0,0x9e,0xe7,0xe1,0xfb,0x3e,0x4a,0x29,0x4c,0xd3,0xc4,0x34,0x4d,0x94,0x52,0xf8,0xbe,0x8f,0xe7,0x79,0x0,0xe4,0xdc,0xfe,0x83,0xac,0x71,0xeb,0x20,0x99,0xeb,0xe6,0x62,0xb1,0xf8,0x6e,0x18,0x4c,0xc3,0x30,0x7c,0x21,0x52,0xda,0xa9,0xd5,0x9e,0x6d,0x44,0xf9,0xf4,0xf4,0x43,0x3a,0x9f,0xcf,0xdf,0xdc,0xde,0xfe,0x6a,0x2f,0x97,0xcb,0x87,0xf9,0x4c,0x5b,0xe3,0x37,0x57,0xdf,0xd7,0x8,0xe6,0x62,0x7d,0xab,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
+static const unsigned char radio_unchecked_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x3,0x1,0x4,0x1b,0x6,0x97,0xfc,0xdf,0x9c,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x1,0x9,0x49,0x44,0x41,0x54,0x38,0xcb,0xad,0x93,0xbd,0x72,0x82,0x40,0x14,0x85,0xf,0x68,0xa,0x9e,0x21,0x8d,0x8e,0x9,0xdb,0xc4,0xc7,0x48,0x41,0x43,0x2b,0xa3,0xad,0x69,0x32,0xc3,0xda,0xc7,0xa7,0x8,0x94,0xa1,0xd,0x68,0x4b,0xc3,0x5b,0xd8,0x5f,0x2d,0xe2,0x60,0xe8,0x99,0xa1,0xd8,0x82,0xc2,0x34,0x17,0x67,0x35,0x19,0x43,0x34,0xa7,0xbc,0x7b,0xee,0x37,0xf7,0x6f,0x81,0x2b,0x65,0x9c,0x6,0x84,0x10,0xb7,0x0,0x7c,0x0,0xe,0x0,0x9b,0xc3,0x6b,0x0,0x19,0x80,0x90,0x88,0x8a,0x1f,0x1,0xdd,0x4e,0x17,0x83,0xbb,0xc1,0x14,0x40,0xe0,0x79,0x13,0x6b,0x3c,0x1e,0x1d,0x81,0xe3,0x78,0x89,0xc5,0xe2,0x5d,0x1,0x90,0x79,0x9e,0x47,0x4a,0xa9,0x63,0x80,0x10,0x62,0xda,0xeb,0xf5,0xdf,0x82,0xe0,0xf5,0x6c,0xc9,0x52,0xce,0xb0,0xdd,0x7e,0x3c,0x11,0x51,0x74,0x0,0x70,0xd9,0x9b,0x34,0x4d,0xad,0x36,0x7d,0xbb,0xae,0xab,0x0,0xdc,0x13,0x51,0x61,0x72,0xcc,0xf7,0xbc,0x89,0xd5,0x76,0x70,0xec,0xf5,0x1,0xa0,0x1,0x38,0xa7,0x3d,0x9f,0x13,0x7b,0x1d,0x1d,0x60,0x5f,0xb0,0x41,0x5b,0x7,0x5c,0x2c,0x53,0xdb,0xf3,0x5f,0xb5,0xd6,0x1,0x59,0x1c,0x2f,0x5b,0x67,0xb2,0x37,0xd3,0x1,0x21,0x1f,0x49,0x2b,0xb1,0x37,0x3c,0x0,0xf8,0x3c,0xa5,0x94,0xb3,0x5f,0x93,0xd9,0x23,0x9b,0x93,0xee,0x34,0xf,0x55,0x55,0xad,0xc,0x3,0x45,0x92,0x24,0x8f,0xfb,0xbd,0x79,0x33,0x1c,0x3e,0x7c,0x2b,0x7b,0x3e,0x7f,0x51,0x65,0x59,0x3e,0xef,0x76,0x9f,0x51,0x5d,0xd7,0xff,0xf3,0x99,0xae,0xd6,0x17,0xf,0x97,0x66,0x8b,0x3d,0xf1,0x64,0x47,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char reference_border_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0x7,0x9,0x11,0x2b,0x1a,0xed,0xf3,0x18,0x82,0x0,0x0,0x0,0x5b,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0xfc,0xbf,0x7d,0xfb,0x7f,0x6,0x6,0x6,0x6,0x86,0xae,0x2e,0x6,0x92,0x40,0x59,0x19,0x84,0x86,0x1b,0x40,0x6,0xf8,0xbf,0x7d,0xfb,0x7f,0xc6,0xff,0x8e,0x8e,0xff,0x19,0xf7,0xef,0x67,0xfc,0x7f,0xf1,0x22,0x49,0x9a,0x19,0xf5,0xf5,0x19,0xfe,0x3b,0x3a,0xfe,0x67,0x41,0x17,0x24,0xca,0x66,0x24,0xcb,0x98,0x18,0x28,0x4,0xa3,0x6,0x8c,0x1a,0xc0,0xc0,0xc0,0xc0,0xc0,0x82,0x2b,0x85,0x91,0x94,0x21,0x28,0xcb,0x4c,0x14,0x66,0x67,0x0,0x0,0x2b,0x27,0xc7,0x5e,0xa8,0x15,0xe4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 3c4bc3ac75..1e3b9772ee 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -108,13 +108,14 @@ void Environment::_bind_methods() {
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"fxaa/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_FXAA);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"background/mode",PROPERTY_HINT_ENUM,"Keep,Default Color,Color,Texture,Cubemap,Texture RGBE,Cubemap RGBE"),_SCS("set_background"),_SCS("get_background"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"background/mode",PROPERTY_HINT_ENUM,"Keep,Default Color,Color,Texture,Cubemap,Canvas"),_SCS("set_background"),_SCS("get_background"));
ADD_PROPERTYI( PropertyInfo(Variant::COLOR,"background/color"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_COLOR);
ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_TEXTURE);
ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/cubemap",PROPERTY_HINT_RESOURCE_TYPE,"CubeMap"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CUBEMAP);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/energy",PROPERTY_HINT_RANGE,"0,128,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_ENERGY);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/scale",PROPERTY_HINT_RANGE,"0.001,16,0.001"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_SCALE);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/glow",PROPERTY_HINT_RANGE,"0.00,8,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_GLOW);
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"background/canvas_max_layer"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CANVAS_MAX_LAYER);
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"glow/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_GLOW);
ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_passes",PROPERTY_HINT_RANGE,"1,4,1"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_PASSES);
@@ -182,10 +183,10 @@ void Environment::_bind_methods() {
BIND_CONSTANT( BG_COLOR );
BIND_CONSTANT( BG_TEXTURE );
BIND_CONSTANT( BG_CUBEMAP );
- BIND_CONSTANT( BG_TEXTURE_RGBE );
- BIND_CONSTANT( BG_CUBEMAP_RGBE );
+ BIND_CONSTANT( BG_CANVAS );
BIND_CONSTANT( BG_MAX );
+ BIND_CONSTANT( BG_PARAM_CANVAS_MAX_LAYER );
BIND_CONSTANT( BG_PARAM_COLOR );
BIND_CONSTANT( BG_PARAM_TEXTURE );
BIND_CONSTANT( BG_PARAM_CUBEMAP );
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index a9e2f422b9..d672a898d5 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -44,14 +44,14 @@ public:
BG_COLOR=VS::ENV_BG_COLOR,
BG_TEXTURE=VS::ENV_BG_TEXTURE,
BG_CUBEMAP=VS::ENV_BG_CUBEMAP,
- BG_TEXTURE_RGBE=VS::ENV_BG_TEXTURE_RGBE,
- BG_CUBEMAP_RGBE=VS::ENV_BG_CUBEMAP_RGBE,
+ BG_CANVAS=VS::ENV_BG_CANVAS,
BG_MAX=VS::ENV_BG_MAX
};
enum BGParam {
- BG_PARAM_COLOR=VS::ENV_BG_PARAM_COLOR,
+ BG_PARAM_CANVAS_MAX_LAYER=VS::ENV_BG_PARAM_CANVAS_MAX_LAYER,
+ BG_PARAM_COLOR=VS::ENV_BG_PARAM_COLOR,
BG_PARAM_TEXTURE=VS::ENV_BG_PARAM_TEXTURE,
BG_PARAM_CUBEMAP=VS::ENV_BG_PARAM_CUBEMAP,
BG_PARAM_ENERGY=VS::ENV_BG_PARAM_ENERGY,
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 49ee3ee017..79316f0019 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -398,6 +398,17 @@ int Font::get_kerning_pair(CharType p_A,CharType p_B) const {
return 0;
}
+void Font::set_distance_field_hint(bool p_distance_field) {
+
+ distance_field_hint=p_distance_field;
+ emit_changed();
+}
+
+bool Font::is_distance_field_hint() const{
+
+ return distance_field_hint;
+}
+
void Font::clear() {
@@ -406,6 +417,7 @@ void Font::clear() {
char_map.clear();
textures.clear();
kerning_map.clear();
+ distance_field_hint=false;
}
Size2 Font::get_string_size(const String& p_string) const {
@@ -511,9 +523,16 @@ void Font::_bind_methods() {
ObjectTypeDB::bind_method(_MD("add_texture","texture:Texture"),&Font::add_texture);
ObjectTypeDB::bind_method(_MD("add_char","character","texture","rect","align","advance"),&Font::add_char,DEFVAL(Point2()),DEFVAL(-1));
+
+ ObjectTypeDB::bind_method(_MD("get_texture_count"),&Font::get_texture_count);
+ ObjectTypeDB::bind_method(_MD("get_texture:Texture","idx"),&Font::get_texture);
+
ObjectTypeDB::bind_method(_MD("get_char_size","char","next"),&Font::get_char_size,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_string_size","string"),&Font::get_string_size);
+ ObjectTypeDB::bind_method(_MD("set_distance_field_hint","enable"),&Font::set_distance_field_hint);
+ ObjectTypeDB::bind_method(_MD("is_distance_field_hint"),&Font::is_distance_field_hint);
+
ObjectTypeDB::bind_method(_MD("clear"),&Font::clear);
ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","string","modulate","clip_w"),&Font::draw,DEFVAL(Color(1,1,1)),DEFVAL(-1));
@@ -535,12 +554,14 @@ void Font::_bind_methods() {
ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,1" ), _SCS("set_height"), _SCS("get_height") );
ADD_PROPERTY( PropertyInfo( Variant::REAL, "ascent", PROPERTY_HINT_RANGE,"-1024,1024,1" ), _SCS("set_ascent"), _SCS("get_ascent") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "distance_field" ), _SCS("set_distance_field_hint"), _SCS("is_distance_field_hint") );
}
Font::Font() {
clear();
+
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index a64ec1ef7a..498bc6863a 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -75,6 +75,7 @@ private:
float height;
float ascent;
+ bool distance_field_hint;
void _set_chars(const DVector<int>& p_chars);
DVector<int> _get_chars() const;
@@ -116,6 +117,9 @@ public:
Size2 get_string_size(const String& p_string) const;
void clear();
+
+ void set_distance_field_hint(bool p_distance_field);
+ bool is_distance_field_hint() const;
void draw(RID p_canvas_item, const Point2& p_pos, const String& p_text,const Color& p_modulate=Color(1,1,1),int p_clip_w=-1) const;
void draw_halign(RID p_canvas_item, const Point2& p_pos, HAlign p_align,float p_width,const String& p_text,const Color& p_modulate=Color(1,1,1)) const;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 2c1502288b..8d3cbadd06 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -321,6 +321,13 @@ void ImageTexture::premultiply_alpha() {
}
}
+void ImageTexture::normal_to_xy() {
+
+ Image img = get_data();
+ img.normalmap_to_xy();
+ create_from_image(img,flags);
+}
+
bool ImageTexture::has_alpha() const {
return ( format==Image::FORMAT_GRAYSCALE_ALPHA || format==Image::FORMAT_INDEXED_ALPHA || format==Image::FORMAT_RGBA );
@@ -405,9 +412,11 @@ void ImageTexture::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality);
ObjectTypeDB::bind_method(_MD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges);
ObjectTypeDB::bind_method(_MD("premultiply_alpha"),&ImageTexture::premultiply_alpha);
+ ObjectTypeDB::bind_method(_MD("normal_to_xy"),&ImageTexture::normal_to_xy);
ObjectTypeDB::bind_method(_MD("set_size_override","size"),&ImageTexture::set_size_override);
ObjectTypeDB::set_method_flags(get_type_static(),_SCS("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
ObjectTypeDB::set_method_flags(get_type_static(),_SCS("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ObjectTypeDB::set_method_flags(get_type_static(),_SCS("normal_to_xy"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
ObjectTypeDB::bind_method(_MD("_reload_hook","rid"),&ImageTexture::_reload_hook);
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index c1122b005d..e853a4b05f 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -146,6 +146,8 @@ public:
void fix_alpha_edges();
void premultiply_alpha();
+ void normal_to_xy();
+
void set_size_override(const Size2& p_size);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 208ba5bb66..338804e0e1 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -46,6 +46,8 @@ bool TileSet::_set(const StringName& p_name, const Variant& p_value) {
tile_set_texture(id,p_value);
else if (what=="tex_offset")
tile_set_texture_offset(id,p_value);
+ else if (what=="material")
+ tile_set_material(id,p_value);
else if (what=="shape_offset")
tile_set_shape_offset(id,p_value);
else if (what=="region")
@@ -54,6 +56,14 @@ bool TileSet::_set(const StringName& p_name, const Variant& p_value) {
tile_set_shape(id,p_value);
else if (what=="shapes")
_tile_set_shapes(id,p_value);
+ else if (what=="occluder")
+ tile_set_light_occluder(id,p_value);
+ else if (what=="occluder_offset")
+ tile_set_occluder_offset(id,p_value);
+ else if (what=="navigation")
+ tile_set_navigation_polygon(id,p_value);
+ else if (what=="navigation_offset")
+ tile_set_navigation_polygon_offset(id,p_value);
else
return false;
@@ -79,6 +89,8 @@ bool TileSet::_get(const StringName& p_name,Variant &r_ret) const{
r_ret=tile_get_texture(id);
else if (what=="tex_offset")
r_ret=tile_get_texture_offset(id);
+ else if (what=="material")
+ r_ret=tile_get_material(id);
else if (what=="shape_offset")
r_ret=tile_get_shape_offset(id);
else if (what=="region")
@@ -87,6 +99,14 @@ bool TileSet::_get(const StringName& p_name,Variant &r_ret) const{
r_ret=tile_get_shape(id);
else if (what=="shapes")
r_ret=_tile_get_shapes(id);
+ else if (what=="occluder")
+ r_ret=tile_get_light_occluder(id);
+ else if (what=="occluder_offset")
+ r_ret=tile_get_occluder_offset(id);
+ else if (what=="navigation")
+ r_ret=tile_get_navigation_polygon(id);
+ else if (what=="navigation_offset")
+ r_ret=tile_get_navigation_polygon_offset(id);
else
return false;
@@ -103,8 +123,13 @@ void TileSet::_get_property_list( List<PropertyInfo> *p_list) const{
p_list->push_back(PropertyInfo(Variant::STRING,pre+"name"));
p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"));
p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"tex_offset"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"shape_offset"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"material",PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemMaterial"));
p_list->push_back(PropertyInfo(Variant::RECT2,pre+"region"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"occluder_offset"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"navigation_offset"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"navigation",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"shape_offset"));
p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_EDITOR));
p_list->push_back(PropertyInfo(Variant::ARRAY,pre+"shapes",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
}
@@ -134,6 +159,22 @@ Ref<Texture> TileSet::tile_get_texture(int p_id) const {
}
+
+void TileSet::tile_set_material(int p_id,const Ref<CanvasItemMaterial> &p_material) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
+ tile_map[p_id].material=p_material;
+ emit_changed();
+
+}
+
+Ref<CanvasItemMaterial> TileSet::tile_get_material(int p_id) const{
+
+ ERR_FAIL_COND_V(!tile_map.has(p_id),Ref<CanvasItemMaterial>());
+ return tile_map[p_id].material;
+}
+
+
void TileSet::tile_set_texture_offset(int p_id,const Vector2 &p_offset) {
ERR_FAIL_COND(!tile_map.has(p_id));
@@ -210,6 +251,58 @@ Ref<Shape2D> TileSet::tile_get_shape(int p_id) const {
}
+void TileSet::tile_set_light_occluder(int p_id,const Ref<OccluderPolygon2D> &p_light_occluder) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
+ tile_map[p_id].occluder=p_light_occluder;
+
+}
+
+Ref<OccluderPolygon2D> TileSet::tile_get_light_occluder(int p_id) const{
+
+ ERR_FAIL_COND_V(!tile_map.has(p_id),Ref<OccluderPolygon2D>());
+ return tile_map[p_id].occluder;
+
+}
+
+void TileSet::tile_set_navigation_polygon_offset(int p_id,const Vector2& p_offset) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
+ tile_map[p_id].navigation_polygon_offset=p_offset;
+
+}
+
+Vector2 TileSet::tile_get_navigation_polygon_offset(int p_id) const{
+ ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2());
+ return tile_map[p_id].navigation_polygon_offset;
+}
+
+void TileSet::tile_set_navigation_polygon(int p_id,const Ref<NavigationPolygon> &p_navigation_polygon) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
+ tile_map[p_id].navigation_polygon=p_navigation_polygon;
+
+}
+
+Ref<NavigationPolygon> TileSet::tile_get_navigation_polygon(int p_id) const {
+
+ ERR_FAIL_COND_V(!tile_map.has(p_id),Ref<NavigationPolygon>());
+ return tile_map[p_id].navigation_polygon;
+
+}
+
+void TileSet::tile_set_occluder_offset(int p_id,const Vector2& p_offset) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
+ tile_map[p_id].occluder_offset=p_offset;
+
+}
+
+Vector2 TileSet::tile_get_occluder_offset(int p_id) const{
+ ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2());
+ return tile_map[p_id].occluder_offset;
+}
+
void TileSet::tile_set_shapes(int p_id,const Vector<Ref<Shape2D> > &p_shapes) {
ERR_FAIL_COND(!tile_map.has(p_id));
@@ -319,6 +412,8 @@ void TileSet::_bind_methods() {
ObjectTypeDB::bind_method(_MD("tile_get_name","id"),&TileSet::tile_get_name);
ObjectTypeDB::bind_method(_MD("tile_set_texture","id","texture:Texture"),&TileSet::tile_set_texture);
ObjectTypeDB::bind_method(_MD("tile_get_texture:Texture","id"),&TileSet::tile_get_texture);
+ ObjectTypeDB::bind_method(_MD("tile_set_material","id","material:CanvasItemMaterial"),&TileSet::tile_set_material);
+ ObjectTypeDB::bind_method(_MD("tile_get_material:CanvasItemMaterial","id"),&TileSet::tile_get_material);
ObjectTypeDB::bind_method(_MD("tile_set_texture_offset","id","texture_offset"),&TileSet::tile_set_texture_offset);
ObjectTypeDB::bind_method(_MD("tile_get_texture_offset","id"),&TileSet::tile_get_texture_offset);
ObjectTypeDB::bind_method(_MD("tile_set_shape_offset","id","shape_offset"),&TileSet::tile_set_shape_offset);
@@ -329,6 +424,15 @@ void TileSet::_bind_methods() {
ObjectTypeDB::bind_method(_MD("tile_get_shape:Shape2D","id"),&TileSet::tile_get_shape);
ObjectTypeDB::bind_method(_MD("tile_set_shapes","id","shapes"),&TileSet::_tile_set_shapes);
ObjectTypeDB::bind_method(_MD("tile_get_shapes","id"),&TileSet::_tile_get_shapes);
+ ObjectTypeDB::bind_method(_MD("tile_set_navigation_polygon","id","navigation_polygon:NavigationPolygon"),&TileSet::tile_set_navigation_polygon);
+ ObjectTypeDB::bind_method(_MD("tile_get_navigation_polygon:NavigationPolygon","id"),&TileSet::tile_get_navigation_polygon);
+ ObjectTypeDB::bind_method(_MD("tile_set_navigation_polygon_offset","id","navigation_polygon_offset"),&TileSet::tile_set_navigation_polygon_offset);
+ ObjectTypeDB::bind_method(_MD("tile_get_navigation_polygon_offset","id"),&TileSet::tile_get_navigation_polygon_offset);
+ ObjectTypeDB::bind_method(_MD("tile_set_light_occluder","id","light_occluder:OccluderPolygon2D"),&TileSet::tile_set_light_occluder);
+ ObjectTypeDB::bind_method(_MD("tile_get_light_occluder:OccluderPolygon2D","id"),&TileSet::tile_get_light_occluder);
+ ObjectTypeDB::bind_method(_MD("tile_set_occluder_offset","id","occluder_offset"),&TileSet::tile_set_occluder_offset);
+ ObjectTypeDB::bind_method(_MD("tile_get_occluder_offset","id"),&TileSet::tile_get_occluder_offset);
+
ObjectTypeDB::bind_method(_MD("remove_tile","id"),&TileSet::remove_tile);
ObjectTypeDB::bind_method(_MD("clear"),&TileSet::clear);
ObjectTypeDB::bind_method(_MD("get_last_unused_tile_id"),&TileSet::get_last_unused_tile_id);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index ddbb1b59a6..0234755a53 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -32,6 +32,8 @@
#include "resource.h"
#include "scene/resources/shape_2d.h"
#include "scene/resources/texture.h"
+#include "scene/2d/light_occluder_2d.h"
+#include "scene/2d/navigation_polygon.h"
class TileSet : public Resource {
@@ -45,6 +47,11 @@ class TileSet : public Resource {
Vector2 shape_offset;
Rect2i region;
Vector<Ref<Shape2D> > shapes;
+ Vector2 occluder_offset;
+ Ref<OccluderPolygon2D> occluder;
+ Vector2 navigation_polygon_offset;
+ Ref<NavigationPolygon> navigation_polygon;
+ Ref<CanvasItemMaterial> material;
};
Map<int,Data> tile_map;
@@ -84,6 +91,21 @@ public:
void tile_set_shape(int p_id,const Ref<Shape2D> &p_shape);
Ref<Shape2D> tile_get_shape(int p_id) const;
+ void tile_set_material(int p_id,const Ref<CanvasItemMaterial> &p_material);
+ Ref<CanvasItemMaterial> tile_get_material(int p_id) const;
+
+ void tile_set_occluder_offset(int p_id,const Vector2& p_offset);
+ Vector2 tile_get_occluder_offset(int p_id) const;
+
+ void tile_set_light_occluder(int p_id,const Ref<OccluderPolygon2D> &p_light_occluder);
+ Ref<OccluderPolygon2D> tile_get_light_occluder(int p_id) const;
+
+ void tile_set_navigation_polygon_offset(int p_id,const Vector2& p_offset);
+ Vector2 tile_get_navigation_polygon_offset(int p_id) const;
+
+ void tile_set_navigation_polygon(int p_id,const Ref<NavigationPolygon> &p_navigation_polygon);
+ Ref<NavigationPolygon> tile_get_navigation_polygon(int p_id) const;
+
void tile_set_shapes(int p_id,const Vector<Ref<Shape2D> > &p_shapes);
Vector<Ref<Shape2D> > tile_get_shapes(int p_id) const;
diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp
index 880a3a32e3..30cf58bdd8 100644
--- a/scene/resources/world.cpp
+++ b/scene/resources/world.cpp
@@ -307,6 +307,11 @@ Ref<Environment> World::get_environment() const {
}
+PhysicsDirectSpaceState *World::get_direct_space_state() {
+
+ return PhysicsServer::get_singleton()->space_get_direct_state(space);
+}
+
void World::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_space"),&World::get_space);
@@ -314,6 +319,7 @@ void World::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_sound_space"),&World::get_sound_space);
ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&World::set_environment);
ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&World::get_environment);
+ ObjectTypeDB::bind_method(_MD("get_direct_space_state:PhysicsDirectSpaceState"),&World::get_direct_space_state);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment"),_SCS("set_environment"),_SCS("get_environment"));
}
diff --git a/scene/resources/world.h b/scene/resources/world.h
index 60b3b99ab0..b10cadd6e0 100644
--- a/scene/resources/world.h
+++ b/scene/resources/world.h
@@ -75,6 +75,8 @@ public:
void set_environment(const Ref<Environment>& p_environment);
Ref<Environment> get_environment() const;
+ PhysicsDirectSpaceState *get_direct_space_state();
+
World();
~World();
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 0dd6a3d5e7..43a7af4bfd 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -352,8 +352,17 @@ void World2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_canvas"),&World2D::get_canvas);
ObjectTypeDB::bind_method(_MD("get_space"),&World2D::get_space);
ObjectTypeDB::bind_method(_MD("get_sound_space"),&World2D::get_sound_space);
+
+ ObjectTypeDB::bind_method(_MD("get_direct_space_state:Physics2DDirectSpaceState"),&World2D::get_direct_space_state);
+
+}
+
+Physics2DDirectSpaceState *World2D::get_direct_space_state() {
+
+ return Physics2DServer::get_singleton()->space_get_direct_state(space);
}
+
World2D::World2D() {
canvas = VisualServer::get_singleton()->canvas_create();
diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h
index 3feb23495d..865ec28fe9 100644
--- a/scene/resources/world_2d.h
+++ b/scene/resources/world_2d.h
@@ -30,7 +30,7 @@
#define WORLD_2D_H
#include "resource.h"
-
+#include "servers/physics_2d_server.h"
class SpatialIndexer2D;
class VisibilityNotifier2D;
@@ -68,6 +68,8 @@ public:
RID get_space();
RID get_sound_space();
+ Physics2DDirectSpaceState *get_direct_space_state();
+
World2D();
~World2D();
};
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index af5e6d4165..d4159f0946 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -41,6 +41,7 @@ SceneStringNames::SceneStringNames() {
visibility_changed=StaticCString::create("visibility_changed");
input_event=StaticCString::create("input_event");
shader_shader=StaticCString::create("shader/shader");
+ shader_unshaded=StaticCString::create("shader/unshaded");
enter_tree=StaticCString::create("enter_tree");
exit_tree=StaticCString::create("exit_tree");
item_rect_changed=StaticCString::create("item_rect_changed");
@@ -63,6 +64,9 @@ SceneStringNames::SceneStringNames() {
body_exit_shape = StaticCString::create("body_exit_shape");
body_exit = StaticCString::create("body_exit");
+ area_enter_shape = StaticCString::create("area_enter_shape");
+ area_exit_shape = StaticCString::create("area_exit_shape");
+
idle=StaticCString::create("idle");
iteration=StaticCString::create("iteration");
@@ -102,6 +106,9 @@ SceneStringNames::SceneStringNames() {
_body_enter_tree = StaticCString::create("_body_enter_tree");
_body_exit_tree = StaticCString::create("_body_exit_tree");
+ _area_enter_tree = StaticCString::create("_area_enter_tree");
+ _area_exit_tree = StaticCString::create("_area_exit_tree");
+
_input_event=StaticCString::create("_input_event");
changed=StaticCString::create("changed");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 14e5e83b8d..aa29ef57dc 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -56,6 +56,7 @@ public:
StringName _input_event;
StringName item_rect_changed;
StringName shader_shader;
+ StringName shader_unshaded;
StringName enter_tree;
StringName exit_tree;
StringName size_flags_changed;
@@ -82,6 +83,10 @@ public:
StringName body_exit_shape;
StringName body_exit;
+ StringName area_enter_shape;
+ StringName area_exit_shape;
+
+
StringName _get_gizmo_geometry;
StringName _can_gizmo_scale;
@@ -123,6 +128,9 @@ public:
StringName _body_enter_tree;
StringName _body_exit_tree;
+ StringName _area_enter_tree;
+ StringName _area_exit_tree;
+
StringName changed;
StringName _shader_changed;
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 725a440b59..c7c20a8bd1 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -358,7 +358,7 @@ void BodySW::_compute_area_gravity(const AreaSW *p_area) {
if (p_area->is_gravity_point()) {
- gravity = (p_area->get_gravity_vector() - get_transform().get_origin()).normalized() * p_area->get_gravity();
+ gravity = (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
} else {
gravity = p_area->get_gravity_vector() * p_area->get_gravity();
diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h
index cdb21556b8..bcf8fbdc8d 100644
--- a/servers/physics/shape_sw.h
+++ b/servers/physics/shape_sw.h
@@ -438,7 +438,7 @@ struct MotionShapeSW : public ShapeSW {
}
return support;
}
- virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const {}
+ virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const { r_amount=0; }
bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const { return false; }
Vector3 get_moment_of_inertia(float p_mass) const { return Vector3(); }
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 4e8b60b86b..3fc34889f2 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -77,7 +77,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
continue;
- if (!(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
+ if (!(static_cast<CollisionObjectSW*>(space->intersection_query_results[i])->is_ray_pickable()))
continue;
if (p_exclude.has( space->intersection_query_results[i]->get_self()))
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index 2e911288ae..65f3b80dd3 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -31,6 +31,7 @@
#include "body_2d_sw.h"
Area2DSW::BodyKey::BodyKey(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; }
+Area2DSW::BodyKey::BodyKey(Area2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; }
void Area2DSW::_shapes_changed() {
@@ -57,6 +58,7 @@ void Area2DSW::set_space(Space2DSW *p_space) {
}
monitored_bodies.clear();
+ monitored_areas.clear();
_set_space(p_space);
}
@@ -76,11 +78,31 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) {
monitor_callback_method=p_method;
monitored_bodies.clear();
+ monitored_areas.clear();
_shape_changed();
}
+void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) {
+
+
+ if (p_id==area_monitor_callback_id) {
+ area_monitor_callback_method=p_method;
+ return;
+ }
+
+ _unregister_shapes();
+
+ area_monitor_callback_id=p_id;
+ area_monitor_callback_method=p_method;
+
+ monitored_bodies.clear();
+ monitored_areas.clear();
+
+ _shape_changed();
+
+}
void Area2DSW::set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode) {
@@ -134,6 +156,15 @@ void Area2DSW::_queue_monitor_update() {
}
+void Area2DSW::set_monitorable(bool p_monitorable) {
+
+ if (monitorable==p_monitorable)
+ return;
+
+ monitorable=p_monitorable;
+ _set_static(!monitorable);
+}
+
void Area2DSW::call_queries() {
if (monitor_callback_id && !monitored_bodies.empty()) {
@@ -170,13 +201,49 @@ void Area2DSW::call_queries() {
monitored_bodies.clear();
+ if (area_monitor_callback_id && !monitored_areas.empty()) {
+
+
+ Variant res[5];
+ Variant *resptr[5];
+ for(int i=0;i<5;i++)
+ resptr[i]=&res[i];
+
+ Object *obj = ObjectDB::get_instance(area_monitor_callback_id);
+ if (!obj) {
+ monitored_areas.clear();
+ area_monitor_callback_id=0;
+ return;
+ }
+
+
+
+ for (Map<BodyKey,BodyState>::Element *E=monitored_areas.front();E;E=E->next()) {
+
+ if (E->get().state==0)
+ continue; //nothing happened
+
+ res[0]=E->get().state>0 ? Physics2DServer::AREA_BODY_ADDED : Physics2DServer::AREA_BODY_REMOVED;
+ res[1]=E->key().rid;
+ res[2]=E->key().instance_id;
+ res[3]=E->key().body_shape;
+ res[4]=E->key().area_shape;
+
+
+ Variant::CallError ce;
+ obj->call(area_monitor_callback_method,(const Variant**)resptr,5,ce);
+ }
+ }
+
+ monitored_areas.clear();
+
//get_space()->area_remove_from_monitor_query_list(&monitor_query_list);
}
Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this), moved_list(this) {
- _set_static(true); //areas are never active
+ _set_static(true); //areas are not active by default
space_override_mode=Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED;
gravity=9.80665;
gravity_vector=Vector2(0,-1);
@@ -187,6 +254,8 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this),
linear_damp=0.1;
priority=0;
monitor_callback_id=0;
+ area_monitor_callback_id=0;
+ monitorable=false;
}
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index d94b2f9ccf..26b7b2516c 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -50,10 +50,14 @@ class Area2DSW : public CollisionObject2DSW{
float linear_damp;
float angular_damp;
int priority;
+ bool monitorable;
ObjectID monitor_callback_id;
StringName monitor_callback_method;
+ ObjectID area_monitor_callback_id;
+ StringName area_monitor_callback_method;
+
SelfList<Area2DSW> monitor_query_list;
SelfList<Area2DSW> moved_list;
@@ -80,6 +84,7 @@ class Area2DSW : public CollisionObject2DSW{
_FORCE_INLINE_ BodyKey() {}
BodyKey(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
+ BodyKey(Area2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
};
struct BodyState {
@@ -91,6 +96,7 @@ class Area2DSW : public CollisionObject2DSW{
};
Map<BodyKey,BodyState> monitored_bodies;
+ Map<BodyKey,BodyState> monitored_areas;
//virtual void shape_changed_notify(Shape2DSW *p_shape);
//virtual void shape_deleted_notify(Shape2DSW *p_shape);
@@ -108,9 +114,16 @@ public:
void set_monitor_callback(ObjectID p_id, const StringName& p_method);
_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id; }
+ void set_area_monitor_callback(ObjectID p_id, const StringName& p_method);
+ _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id; }
+
+
_FORCE_INLINE_ void add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
_FORCE_INLINE_ void remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
+ _FORCE_INLINE_ void add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape);
+ _FORCE_INLINE_ void remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape);
+
void set_param(Physics2DServer::AreaParameter p_param, const Variant& p_value);
Variant get_param(Physics2DServer::AreaParameter p_param) const;
@@ -142,6 +155,9 @@ public:
_FORCE_INLINE_ void remove_constraint( Constraint2DSW* p_constraint) { constraints.erase(p_constraint); }
_FORCE_INLINE_ const Set<Constraint2DSW*>& get_constraints() const { return constraints; }
+ void set_monitorable(bool p_monitorable);
+ _FORCE_INLINE_ bool is_monitorable() const { return monitorable; }
+
void set_transform(const Matrix32& p_transform);
void set_space(Space2DSW *p_space);
@@ -168,6 +184,24 @@ void Area2DSW::remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape,ui
_queue_monitor_update();
}
+void Area2DSW::add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) {
+
+
+ BodyKey bk(p_area,p_area_shape,p_self_shape);
+ monitored_areas[bk].inc();
+ if (!monitor_query_list.in_list())
+ _queue_monitor_update();
+
+
+}
+void Area2DSW::remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) {
+
+
+ BodyKey bk(p_area,p_area_shape,p_self_shape);
+ monitored_areas[bk].dec();
+ if (!monitor_query_list.in_list())
+ _queue_monitor_update();
+}
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 1c7f73db5e..ed2e34c972 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -94,3 +94,72 @@ AreaPair2DSW::~AreaPair2DSW() {
body->remove_constraint(this);
area->remove_constraint(this);
}
+
+
+//////////////////////////////////
+
+
+
+bool Area2Pair2DSW::setup(float p_step) {
+
+ bool result = CollisionSolver2DSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this);
+
+ if (result!=colliding) {
+
+ if (result) {
+
+ if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
+ area_b->add_area_to_query(area_a,shape_a,shape_b);
+
+ if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
+ area_a->add_area_to_query(area_b,shape_b,shape_a);
+
+ } else {
+
+ if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
+ area_b->remove_area_from_query(area_a,shape_a,shape_b);
+
+ if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
+ area_a->remove_area_from_query(area_b,shape_b,shape_a);
+ }
+
+ colliding=result;
+
+ }
+
+ return false; //never do any post solving
+}
+
+void Area2Pair2DSW::solve(float p_step) {
+
+
+}
+
+
+Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a,int p_shape_a, Area2DSW *p_area_b,int p_shape_b) {
+
+
+ area_a=p_area_a;
+ area_b=p_area_b;
+ shape_a=p_shape_a;
+ shape_b=p_shape_b;
+ colliding=false;
+ area_a->add_constraint(this);
+ area_b->add_constraint(this);
+
+}
+
+Area2Pair2DSW::~Area2Pair2DSW() {
+
+ if (colliding) {
+
+ if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
+ area_b->remove_area_from_query(area_a,shape_a,shape_b);
+
+ if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
+ area_a->remove_area_from_query(area_b,shape_b,shape_a);
+ }
+
+ area_a->remove_constraint(this);
+ area_b->remove_constraint(this);
+}
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h
index 5dad8c7a12..575490b109 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/area_pair_2d_sw.h
@@ -49,5 +49,23 @@ public:
~AreaPair2DSW();
};
+
+class Area2Pair2DSW : public Constraint2DSW {
+
+ Area2DSW *area_a;
+ Area2DSW *area_b;
+ int shape_a;
+ int shape_b;
+ bool colliding;
+public:
+
+ bool setup(float p_step);
+ void solve(float p_step);
+
+ Area2Pair2DSW(Area2DSW *p_area_a,int p_shape_a, Area2DSW *p_area_b,int p_shape_b);
+ ~Area2Pair2DSW();
+};
+
+
#endif // AREA_PAIR_2D_SW_H
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 1cfe9a6ab9..06d466ace8 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -379,7 +379,7 @@ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) {
if (p_area->is_gravity_point()) {
- gravity = (p_area->get_transform().get_origin()+p_area->get_gravity_vector() - get_transform().get_origin()).normalized() * p_area->get_gravity();
+ gravity = (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
} else {
gravity = p_area->get_gravity_vector() * p_area->get_gravity();
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index d0443f8110..eefc598b39 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -228,4 +228,5 @@ CollisionObject2DSW::CollisionObject2DSW(Type p_type) {
instance_id=0;
user_mask=0;
layer_mask=1;
+ pickable=true;
}
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index 00ad361245..0c91237876 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -47,6 +47,7 @@ private:
Type type;
RID self;
ObjectID instance_id;
+ bool pickable;
struct Shape {
@@ -129,6 +130,9 @@ public:
_FORCE_INLINE_ bool is_static() const { return _static; }
+ void set_pickable(bool p_pickable) { pickable=p_pickable; }
+ _FORCE_INLINE_ bool is_pickable() const { return pickable; }
+
virtual ~CollisionObject2DSW() {}
};
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index be49955055..883acd0200 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -463,6 +463,24 @@ Matrix32 Physics2DServerSW::area_get_transform(RID p_area) const {
return area->get_transform();
};
+void Physics2DServerSW::area_set_pickable(RID p_area,bool p_pickable) {
+
+ Area2DSW *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_pickable(p_pickable);
+
+}
+
+void Physics2DServerSW::area_set_monitorable(RID p_area,bool p_monitorable) {
+
+ Area2DSW *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_monitorable(p_monitorable);
+
+}
+
+
void Physics2DServerSW::area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) {
Area2DSW *area = area_owner.get(p_area);
@@ -473,6 +491,14 @@ void Physics2DServerSW::area_set_monitor_callback(RID p_area,Object *p_receiver,
}
+void Physics2DServerSW::area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) {
+
+
+ Area2DSW *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_area_monitor_callback(p_receiver?p_receiver->get_instance_ID():0,p_method);
+}
/* BODY API */
@@ -925,6 +951,13 @@ bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_s
}
+void Physics2DServerSW::body_set_pickable(RID p_body,bool p_pickable) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_pickable(p_pickable);
+
+}
/* JOINT API */
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index e9c499aaff..58fc4eeb33 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -133,8 +133,12 @@ public:
virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const;
virtual Matrix32 area_get_transform(RID p_area) const;
+ virtual void area_set_monitorable(RID p_area,bool p_monitorable);
virtual void area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method);
+ virtual void area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method);
+
+ virtual void area_set_pickable(RID p_area,bool p_pickable);
/* BODY API */
@@ -217,6 +221,8 @@ public:
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count);
+ virtual void body_set_pickable(RID p_body,bool p_pickable);
+
/* JOINT API */
virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value);
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index ed63870a12..9a4b52d563 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -106,6 +106,11 @@ void LineShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,int
r_amount=0;
}
+bool LineShape2DSW::contains_point(const Vector2& p_point) const {
+
+ return normal.dot(p_point) < d;
+}
+
bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
Vector2 segment= p_begin - p_end;
@@ -175,6 +180,11 @@ void RayShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,int
}
+bool RayShape2DSW::contains_point(const Vector2& p_point) const {
+
+ return false;
+}
+
bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
return false; //rays can't be intersected
@@ -223,6 +233,11 @@ void SegmentShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
}
+bool SegmentShape2DSW::contains_point(const Vector2& p_point) const {
+
+ return false;
+}
+
bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
if (!Geometry::segment_intersects_segment_2d(p_begin,p_end,a,b,&r_point))
@@ -288,6 +303,13 @@ void CircleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,i
}
+
+bool CircleShape2DSW::contains_point(const Vector2& p_point) const {
+
+ return p_point.length_squared() < radius*radius;
+}
+
+
bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
@@ -375,6 +397,11 @@ void RectangleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_support
}
+bool RectangleShape2DSW::contains_point(const Vector2& p_point) const {
+
+ return Math::abs(p_point.x)<half_extents.x && Math::abs(p_point.y)<half_extents.y;
+}
+
bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
@@ -439,6 +466,17 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
}
}
+bool CapsuleShape2DSW::contains_point(const Vector2& p_point) const {
+
+ Vector2 p = p_point;
+ p.y=Math::abs(p.y);
+ p.y-=height*0.5;
+ if (p.y<0)
+ p.y=0;
+
+ return p.length_squared() < radius*radius;
+}
+
bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
@@ -574,6 +612,25 @@ void ConvexPolygonShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_sup
}
+
+bool ConvexPolygonShape2DSW::contains_point(const Vector2& p_point) const {
+
+ bool out=false;
+ bool in=false;
+
+ for(int i=0;i<point_count;i++) {
+
+ float d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos);
+ if (d>0)
+ out=true;
+ else
+ in=true;
+ }
+
+ return (in && !out) || (!in && out);
+}
+
+
bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
Vector2 n = (p_end-p_begin).normalized();
@@ -734,6 +791,12 @@ void ConcavePolygonShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_su
}
+bool ConcavePolygonShape2DSW::contains_point(const Vector2& p_point) const {
+
+ return false; //sorry
+}
+
+
bool ConcavePolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const{
uint32_t* stack = (uint32_t*)alloca(sizeof(int)*bvh_depth);
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index 931491efd5..05ea5b21cd 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -78,6 +78,8 @@ public:
virtual bool is_concave() const { return false; }
+ virtual bool contains_point(const Vector2& p_point) const=0;
+
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0;
virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0;
virtual Vector2 get_support(const Vector2& p_normal) const;
@@ -171,6 +173,7 @@ public:
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
@@ -213,6 +216,7 @@ public:
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
@@ -260,6 +264,7 @@ public:
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
@@ -297,6 +302,7 @@ public:
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
@@ -336,6 +342,7 @@ public:
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
@@ -423,6 +430,7 @@ public:
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
@@ -485,6 +493,7 @@ public:
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
@@ -572,6 +581,7 @@ public:
virtual void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
+ virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { return 0; }
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index f2ed74ffbf..5aaf9a7613 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -45,6 +45,57 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_objec
}
+
+int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+
+ if (p_result_max<=0)
+ return 0;
+
+ Rect2 aabb;
+ aabb.pos=p_point-Vector2(0.00001,0.00001);
+ aabb.size=Vector2(0.00002,0.00002);
+
+ int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
+
+ int cc=0;
+
+ for(int i=0;i<amount;i++) {
+
+ if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
+ continue;
+
+ if (p_exclude.has( space->intersection_query_results[i]->get_self()))
+ continue;
+
+ const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
+
+ if (!col_obj->is_pickable())
+ continue;
+
+ int shape_idx=space->intersection_query_subindex_results[i];
+
+ Shape2DSW * shape = col_obj->get_shape(shape_idx);
+
+ Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point);
+
+ if (!shape->contains_point(local_point))
+ continue;
+
+ r_results[cc].collider_id=col_obj->get_instance_id();
+ if (r_results[cc].collider_id!=0)
+ r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id);
+ r_results[cc].rid=col_obj->get_self();
+ r_results[cc].shape=shape_idx;
+ r_results[cc].metadata=col_obj->get_shape_metadata(shape_idx);
+
+ cc++;
+ }
+
+ return cc;
+
+
+}
+
bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
@@ -527,13 +578,20 @@ void* Space2DSW::_broadphase_pair(CollisionObject2DSW *A,int p_subindex_A,Collis
if (type_A==CollisionObject2DSW::TYPE_AREA) {
- ERR_FAIL_COND_V(type_B!=CollisionObject2DSW::TYPE_BODY,NULL);
Area2DSW *area=static_cast<Area2DSW*>(A);
- Body2DSW *body=static_cast<Body2DSW*>(B);
+ if (type_B==CollisionObject2DSW::TYPE_AREA) {
+
+ Area2DSW *area_b=static_cast<Area2DSW*>(B);
+ Area2Pair2DSW *area2_pair = memnew(Area2Pair2DSW(area_b,p_subindex_B,area,p_subindex_A) );
+ return area2_pair;
+ } else {
+
+ Body2DSW *body=static_cast<Body2DSW*>(B);
+ AreaPair2DSW *area_pair = memnew(AreaPair2DSW(body,p_subindex_B,area,p_subindex_A) );
+ return area_pair;
+ }
- AreaPair2DSW *area_pair = memnew(AreaPair2DSW(body,p_subindex_B,area,p_subindex_A) );
- return area_pair;
} else {
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 7977b19063..05b55fe807 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -46,6 +46,7 @@ public:
Space2DSW *space;
+ virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index 07389bc912..098f890222 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -289,6 +289,36 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam
return ret;
}
+
+Array Physics2DDirectSpaceState::_intersect_point(const Vector2& p_point,int p_max_results,const Vector<RID>& p_exclude,uint32_t p_layers,uint32_t p_object_type_mask) {
+
+ Set<RID> exclude;
+ for(int i=0;i<p_exclude.size();i++)
+ exclude.insert(p_exclude[i]);
+
+ Vector<ShapeResult> ret;
+ ret.resize(p_max_results);
+
+ int rc = intersect_point(p_point,ret.ptr(),ret.size(),exclude,p_layers,p_object_type_mask);
+ if (rc==0)
+ return Array();
+
+ Array r;
+ r.resize(rc);
+ for(int i=0;i<rc;i++) {
+
+ Dictionary d;
+ d["rid"]=ret[i].rid;
+ d["collider_id"]=ret[i].collider_id;
+ d["collider"]=ret[i].collider;
+ d["shape"]=ret[i].shape;
+ d["metadata"]=ret[i].metadata;
+ r[i]=d;
+ }
+ return r;
+
+}
+
Array Physics2DDirectSpaceState::_collide_shape(const Ref<Physics2DShapeQueryParameters> &psq, int p_max_results){
Vector<Vector2> ret;
@@ -336,6 +366,7 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() {
void Physics2DDirectSpaceState::_bind_methods() {
+ ObjectTypeDB::bind_method(_MD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
ObjectTypeDB::bind_method(_MD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32));
ObjectTypeDB::bind_method(_MD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 765cebf45f..01670ace7e 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -137,6 +137,7 @@ class Physics2DDirectSpaceState : public Object {
Dictionary _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ Array _intersect_point(const Vector2& p_point,int p_max_results=32,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query,int p_max_results=32);
Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query);
Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query,int p_max_results=32);
@@ -181,6 +182,8 @@ public:
};
+ virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
+
virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
@@ -341,7 +344,11 @@ public:
virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const=0;
virtual Matrix32 area_get_transform(RID p_area) const=0;
+ virtual void area_set_monitorable(RID p_area,bool p_monitorable)=0;
+ virtual void area_set_pickable(RID p_area,bool p_pickable)=0;
+
virtual void area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method)=0;
+ virtual void area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method)=0;
/* BODY API */
@@ -459,6 +466,8 @@ public:
virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count)=0;
+ virtual void body_set_pickable(RID p_body,bool p_pickable)=0;
+
/* JOINT API */
enum JointType {
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp
index c3dcd83a31..5088000022 100644
--- a/servers/visual/rasterizer.cpp
+++ b/servers/visual/rasterizer.cpp
@@ -91,7 +91,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
scode+="uniform float fmp_normal;\n";
scode+="uniform texture fmp_normal_tex;\n";
String uv_str;
- if ((p_key.texcoord_mask>>(VS::FIXED_MATERIAL_PARAM_NORMAL*2))&0x3==VS::FIXED_MATERIAL_TEXCOORD_SPHERE) {
+ if (((p_key.texcoord_mask>>(VS::FIXED_MATERIAL_PARAM_NORMAL*2))&0x3)==VS::FIXED_MATERIAL_TEXCOORD_SPHERE) {
uv_str="uv"; //sorry not supported
} else {
uv_str=_TEXUVSTR(VS::FIXED_MATERIAL_PARAM_NORMAL);
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 4c9d0491b1..ebc210fe3d 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -572,35 +572,42 @@ public:
struct CanvasLight {
+
bool enabled;
- bool shadow;
Color color;
Matrix32 xform;
float height;
+ float scale;
int z_min;
int z_max;
int layer_min;
int layer_max;
int item_mask;
+ int item_shadow_mask;
bool subtract;
RID texture;
Vector2 texture_offset;
RID canvas;
+ RID shadow_buffer;
+ int shadow_buffer_size;
+ float shadow_esm_mult;
void *texture_cache; // implementation dependent
Rect2 rect_cache;
Matrix32 xform_cache;
+ float radius_cache; //used for shadow far plane
+ CameraMatrix shadow_matrix_cache;
Matrix32 light_shader_xform;
Vector2 light_shader_pos;
+ CanvasLight *shadows_next_ptr;
CanvasLight *filter_next_ptr;
CanvasLight *next_ptr;
CanvasLight() {
- enabled=true;
- shadow=false;
+ enabled=true;
color=Color(1,1,1);
height=0;
z_min=-1024;
@@ -608,13 +615,30 @@ public:
layer_min=0;
layer_max=0;
item_mask=1;
+ scale=1.0;
+ item_shadow_mask=-1;
subtract=false;
texture_cache=NULL;
next_ptr=NULL;
filter_next_ptr=NULL;
+ shadow_buffer_size=2048;
+ shadow_esm_mult=80;
+
}
};
+ struct CanvasItem;
+
+ struct CanvasItemMaterial {
+
+ RID shader;
+ Map<StringName,Variant> shader_param;
+ uint32_t shader_version;
+ Set<CanvasItem*> owners;
+ bool unshaded;
+
+ CanvasItemMaterial() {unshaded=false; shader_version=0; }
+ };
struct CanvasItem {
@@ -744,17 +768,22 @@ public:
mutable bool rect_dirty;
mutable Rect2 rect;
CanvasItem*next;
- RID shader;
- Map<StringName,Variant> shader_param;
- uint32_t shader_version;
+ CanvasItemMaterial* material;
+ struct CopyBackBuffer {
+ Rect2 rect;
+ Rect2 screen_rect;
+ bool full;
+ };
+ CopyBackBuffer *copy_back_buffer;
float final_opacity;
Matrix32 final_transform;
Rect2 final_clip_rect;
CanvasItem* final_clip_owner;
- CanvasItem* shader_owner;
+ CanvasItem* material_owner;
ViewportRender *vp_render;
+ bool distance_field;
Rect2 global_rect_cache;
@@ -881,15 +910,16 @@ public:
return rect;
}
- void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; shader_owner=NULL;}
- CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; shader_version=0; shader_owner=NULL;}
- virtual ~CanvasItem() { clear(); }
+ void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL;}
+ CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; }
+ virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
};
CanvasItemDrawViewportFunc draw_viewport_func;
+ virtual void begin_canvas_bg()=0;
virtual void canvas_begin()=0;
virtual void canvas_disable_blending()=0;
virtual void canvas_set_opacity(float p_opacity)=0;
@@ -905,7 +935,36 @@ public:
virtual void canvas_set_transform(const Matrix32& p_transform)=0;
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0;
+ virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0;
+ /* LIGHT SHADOW MAPPING */
+
+ virtual RID canvas_light_occluder_create()=0;
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines)=0;
+
+ virtual RID canvas_light_shadow_buffer_create(int p_width)=0;
+
+ struct CanvasLightOccluderInstance {
+
+
+ bool enabled;
+ RID canvas;
+ RID polygon;
+ RID polygon_buffer;
+ Rect2 aabb_cache;
+ Matrix32 xform;
+ Matrix32 xform_cache;
+ int light_mask;
+ VS::CanvasOccluderPolygonCullMode cull_cache;
+
+ CanvasLightOccluderInstance *next;
+
+ CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0;
/* ENVIRONMENT */
@@ -945,6 +1004,8 @@ public:
virtual bool is_environment(const RID& p_rid) const=0;
virtual bool is_shader(const RID& p_rid) const=0;
+ virtual bool is_canvas_light_occluder(const RID& p_rid) const=0;
+
virtual void free(const RID& p_rid)=0;
virtual void init()=0;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index dfa0172e82..af65a7a639 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -56,6 +56,7 @@ const char * ShaderLanguage::token_names[TK_MAX]={
"TYPE_VEC2",
"TYPE_VEC3",
"TYPE_VEC4",
+ "TYPE_MAT2",
"TYPE_MAT3",
"TYPE_MAT4",
"TYPE_TEXTURE",
@@ -403,9 +404,9 @@ ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_le
{TK_TYPE_TEXTURE,"texture"},
{TK_TYPE_CUBEMAP,"cubemap"},
{TK_TYPE_COLOR,"color"},
- /*
+
{TK_TYPE_MAT2,"mat2"},
- {TK_TYPE_MAT3,"mat3"},
+ /*{TK_TYPE_MAT3,"mat3"},
{TK_TYPE_MAT4,"mat3"},*/
{TK_TYPE_MAT3,"mat3"},
{TK_TYPE_MAT4,"mat4"},
@@ -511,6 +512,7 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) {
(p_type==TK_TYPE_VEC3) ||
(p_type==TK_TYPE_VEC4) ||
(p_type==TK_TYPE_COLOR) ||
+ (p_type==TK_TYPE_MAT2) ||
(p_type==TK_TYPE_MAT3) ||
(p_type==TK_TYPE_MAT4) ||
(p_type==TK_TYPE_CUBEMAP) ||
@@ -529,6 +531,7 @@ ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) {
case TK_TYPE_VEC3: return TYPE_VEC3;
case TK_TYPE_VEC4: return TYPE_VEC4;
case TK_TYPE_COLOR: return TYPE_VEC4;
+ case TK_TYPE_MAT2: return TYPE_MAT2;
case TK_TYPE_MAT3: return TYPE_MAT3;
case TK_TYPE_MAT4: return TYPE_MAT4;
case TK_TYPE_TEXTURE: return TYPE_TEXTURE;
@@ -550,6 +553,7 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
case TYPE_VEC2: return "vec2";
case TYPE_VEC3: return "vec3";
case TYPE_VEC4: return "vec4";
+ case TYPE_MAT2: return "mat2";
case TYPE_MAT3: return "mat3";
case TYPE_MAT4: return "mat4";
case TYPE_TEXTURE: return "texture";
@@ -570,6 +574,7 @@ bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
(p_type==TK_TYPE_VEC3) ||
(p_type==TK_TYPE_VEC4) ||
(p_type==TK_TYPE_COLOR) ||
+ (p_type==TK_TYPE_MAT2) ||
(p_type==TK_TYPE_MAT3) ||
(p_type==TK_TYPE_MAT4) ||
(p_type==TK_TYPE_TEXTURE) ||
@@ -782,6 +787,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}},
{"vec4",TYPE_VEC4,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
{"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"mat2",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
{"mat3",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
{"mat4",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
//intrinsics - trigonometry
@@ -918,6 +924,7 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={
{OP_ASSIGN,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}},
{OP_ASSIGN,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}},
{OP_ASSIGN,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}},
+ {OP_ASSIGN,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}},
{OP_ASSIGN,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}},
{OP_ASSIGN,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}},
{OP_ADD,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}},
@@ -933,6 +940,8 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={
{OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}},
{OP_MUL,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}},
{OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT3}},
+ {OP_MUL,TYPE_VEC2,{TYPE_MAT2,TYPE_VEC2}},
+ {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT2}},
{OP_MUL,TYPE_VEC2,{TYPE_MAT3,TYPE_VEC2}},
{OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT4}},
{OP_MUL,TYPE_VEC2,{TYPE_MAT4,TYPE_VEC2}},
@@ -947,6 +956,7 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={
{OP_MUL,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}},
{OP_MUL,TYPE_VEC4,{TYPE_MAT4,TYPE_VEC4}},
{OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_MAT4}},
+ {OP_MUL,TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2}},
{OP_MUL,TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3}},
{OP_MUL,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}},
{OP_DIV,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}},
@@ -976,15 +986,15 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_VEC2}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_VEC2}},
+ {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_MAT2}},
+ {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}},
+ {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT3}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_VEC3}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_VEC3}},
+ {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT4}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_VEC4}},
+ {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_MAT4}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}},
{OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}},
{OP_ASSIGN_DIV,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}},
@@ -1149,11 +1159,19 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={
const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={
- { "COLOR", TYPE_VEC4},
+ { "POSITION", TYPE_VEC4},
{ "NORMAL", TYPE_VEC3},
- { "LIGHT_DIR", TYPE_VEC2},
- { "LIGHT_DISTANCE", TYPE_FLOAT},
- { "LIGHT", TYPE_VEC3},
+ { "UV", TYPE_VEC2},
+ { "COLOR", TYPE_VEC4},
+ { "TEXTURE", TYPE_TEXTURE},
+ { "TEXTURE_PIXEL_SIZE", TYPE_VEC2},
+ { "VAR1", TYPE_VEC4},
+ { "VAR2", TYPE_VEC4},
+ { "SCREEN_UV", TYPE_VEC2},
+ { "LIGHT_VEC", TYPE_VEC2},
+ { "LIGHT_HEIGHT", TYPE_FLOAT},
+ { "LIGHT_COLOR", TYPE_VEC4},
+ { "LIGHT", TYPE_VEC4},
{ "POINT_COORD", TYPE_VEC2},
// { "SCREEN_POS", TYPE_VEC2},
// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
@@ -1558,6 +1576,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
case TYPE_VEC2: name="vec2"; break;
case TYPE_VEC3: name="vec3"; break;
case TYPE_VEC4: name="vec4"; break;
+ case TYPE_MAT2: name="mat2"; break;
case TYPE_MAT3: name="mat3"; break;
case TYPE_MAT4: name="mat4"; break;
default: ERR_FAIL_V(ERR_BUG);
@@ -1852,6 +1871,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
}
} break;
+ case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break;
case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break;
case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break;
default: {}
@@ -2059,7 +2079,9 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
at+=get_datatype_name(compute_node_type(op->arguments[i]));
}
- parser.set_error("Invalid arguments to operator "+String(token_names[op->op])+": "+at);
+ static const char *op_names[OP_MAX]={"=","+","-","*","/","+=","-=","*=","/=","-","!","==","!=","<=",">=","<",">","||","&&","call","()"};
+
+ parser.set_error("Invalid arguments to operator "+String(op_names[op->op])+": "+at);
return ERR_PARSE_ERROR;
}
expression.remove(next_op);
@@ -2236,6 +2258,7 @@ Error ShaderLanguage::parse_variable_declaration(Parser& parser,BlockNode *p_blo
case TYPE_VEC2: con->value=Vector2(); break;
case TYPE_VEC3: con->value=Vector3(); break;
case TYPE_VEC4: con->value=iscolor?Variant(Color()):Variant(Plane()); break;
+ case TYPE_MAT2: con->value=Matrix32(); break;
case TYPE_MAT3: con->value=Matrix3(); break;
case TYPE_MAT4: con->value=Transform(); break;
case TYPE_TEXTURE:
@@ -2618,12 +2641,20 @@ void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keyword
int idx=0;
+ p_keywords->push_back("uniform");
+ p_keywords->push_back("texture");
+ p_keywords->push_back("cubemap");
+ p_keywords->push_back("color");
+ p_keywords->push_back("if");
+ p_keywords->push_back("else");
+
while(intrinsic_func_defs[idx].name) {
p_keywords->push_back(intrinsic_func_defs[idx].name);
idx++;
}
+
switch(p_type) {
case SHADER_MATERIAL_VERTEX: {
idx=0;
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index f79c219d85..7777c8bcf3 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -56,6 +56,7 @@ public:
TK_TYPE_VEC2,
TK_TYPE_VEC3,
TK_TYPE_VEC4,
+ TK_TYPE_MAT2,
TK_TYPE_MAT3,
TK_TYPE_MAT4,
TK_TYPE_TEXTURE,
@@ -118,6 +119,7 @@ public:
TYPE_VEC2,
TYPE_VEC3,
TYPE_VEC4,
+ TYPE_MAT2,
TYPE_MAT3,
TYPE_MAT4,
TYPE_TEXTURE,
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 764a969e77..83bfbbc6c3 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -1693,6 +1693,17 @@ void VisualServerRaster::viewport_set_hide_canvas(RID p_viewport,bool p_hide) {
}
+void VisualServerRaster::viewport_set_disable_environment(RID p_viewport,bool p_disable) {
+
+ VS_CHANGED;
+
+ Viewport *viewport=NULL;
+ viewport = viewport_owner.get( p_viewport );
+ ERR_FAIL_COND(!viewport);
+ viewport->disable_environment=p_disable;
+
+}
+
void VisualServerRaster::viewport_attach_camera(RID p_viewport,RID p_camera) {
VS_CHANGED;
@@ -3400,6 +3411,14 @@ void VisualServerRaster::canvas_item_set_clip(RID p_item, bool p_clip) {
canvas_item->clip=p_clip;
}
+void VisualServerRaster::canvas_item_set_distance_field_mode(RID p_item, bool p_distance_field) {
+ VS_CHANGED;
+ CanvasItem *canvas_item = canvas_item_owner.get( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->distance_field=p_distance_field;
+}
+
void VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) {
@@ -3765,55 +3784,53 @@ void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, boo
}
-void VisualServerRaster::canvas_item_set_use_parent_shader(RID p_item, bool p_enable) {
+void VisualServerRaster::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2& p_rect) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
- canvas_item->use_parent_shader=p_enable;
+ if (bool(canvas_item->copy_back_buffer!=NULL) !=p_enable) {
+ if (p_enable) {
+ canvas_item->copy_back_buffer = memnew( Rasterizer::CanvasItem::CopyBackBuffer );
+ } else {
+ memdelete(canvas_item->copy_back_buffer);
+ canvas_item->copy_back_buffer=NULL;
+ }
+ }
+
+ if (p_enable) {
+ canvas_item->copy_back_buffer->rect=p_rect;
+ canvas_item->copy_back_buffer->full=p_rect==Rect2();
+ }
}
-void VisualServerRaster::canvas_item_set_shader(RID p_item, RID p_shader) {
+void VisualServerRaster::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
- canvas_item->shader=p_shader;
-}
-
-RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{
-
- CanvasItem *canvas_item = canvas_item_owner.get( p_item );
- ERR_FAIL_COND_V(!canvas_item,RID());
- return canvas_item->shader;
+ canvas_item->use_parent_material=p_enable;
}
-void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){
+void VisualServerRaster::canvas_item_set_material(RID p_item, RID p_material) {
VS_CHANGED;
- CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
+ CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
- if (p_value.get_type()==Variant::NIL)
- canvas_item->shader_param.erase(p_param);
- else
- canvas_item->shader_param[p_param]=p_value;
-}
-Variant VisualServerRaster::canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const{
+ if (canvas_item->material)
+ canvas_item->material->owners.erase(canvas_item);
- CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
- ERR_FAIL_COND_V(!canvas_item,Variant());
- if (!canvas_item->shader_param.has(p_param)) {
- ERR_FAIL_COND_V(!canvas_item->shader.is_valid(),Variant());
- return rasterizer->shader_get_default_param(canvas_item->shader,p_param);
- }
+ canvas_item->material=NULL;
- return canvas_item->shader_param[p_param];
+ if (canvas_item_material_owner.owns(p_material)) {
+ canvas_item->material=canvas_item_material_owner.get(p_material);
+ canvas_item->material->owners.insert(canvas_item);
+ }
}
-
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
VS_CHANGED;
@@ -3922,6 +3939,15 @@ void VisualServerRaster::canvas_light_set_transform(RID p_light, const Matrix32&
clight->xform=p_transform;
}
+void VisualServerRaster::canvas_light_set_scale(RID p_light, float p_scale) {
+
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->scale=p_scale;
+
+}
+
+
void VisualServerRaster::canvas_light_set_texture(RID p_light, RID p_texture){
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
@@ -3977,6 +4003,15 @@ void VisualServerRaster::canvas_light_set_item_mask(RID p_light, int p_mask){
}
+void VisualServerRaster::canvas_light_set_item_shadow_mask(RID p_light, int p_mask){
+
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->item_shadow_mask=p_mask;
+
+}
+
+
void VisualServerRaster::canvas_light_set_subtract_mode(RID p_light, bool p_enable) {
@@ -3989,19 +4024,41 @@ void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_ena
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
- clight->shadow=p_enabled;
+
+ if (clight->shadow_buffer.is_valid()==p_enabled)
+ return;
+ if (p_enabled) {
+ clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ } else {
+ rasterizer->free(clight->shadow_buffer);
+ clight->shadow_buffer=RID();
+
+ }
}
+
void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
+ ERR_FAIL_COND(p_size<32 || p_size>16384);
+
+ clight->shadow_buffer_size=nearest_power_of_2(p_size);
+
+
+ if (clight->shadow_buffer.is_valid()) {
+ rasterizer->free(clight->shadow_buffer);
+ clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ }
+
}
-void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size){
+
+void VisualServerRaster::canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier) {
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
+ clight->shadow_esm_mult=p_multiplier;
}
@@ -4009,24 +4066,215 @@ void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size)
RID VisualServerRaster::canvas_light_occluder_create() {
- return RID();
+ Rasterizer::CanvasLightOccluderInstance *occluder = memnew( Rasterizer::CanvasLightOccluderInstance );
+
+ return canvas_light_occluder_owner.make_rid( occluder );
+
}
void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas) {
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.erase(occluder);
+ }
+
+ if (!canvas_owner.owns(p_canvas))
+ p_canvas=RID();
+
+ occluder->canvas=p_canvas;
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.insert(occluder);
+ }
}
void VisualServerRaster::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled){
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->enabled=p_enabled;
+
+}
+
+void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->polygon.is_valid()) {
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+ }
+
+ occluder->polygon=p_polygon;
+ occluder->polygon_buffer=RID();
+
+ if (occluder->polygon.is_valid()) {
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (!occluder_poly)
+ occluder->polygon=RID();
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->owners.insert(occluder);
+ occluder->polygon_buffer=occluder_poly->occluder;
+ occluder->aabb_cache=occluder_poly->aabb;
+ occluder->cull_cache=occluder_poly->cull_mode;
+ }
+
+}
+
+
+
+
+void VisualServerRaster::canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->xform=p_xform;
+
+}
+
+void VisualServerRaster::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->light_mask=p_mask;
+
+}
+
+
+RID VisualServerRaster::canvas_occluder_polygon_create() {
+
+ CanvasLightOccluderPolygon * occluder_poly = memnew( CanvasLightOccluderPolygon );
+ occluder_poly->occluder=rasterizer->canvas_light_occluder_create();
+ return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
+
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const DVector<Vector2>& p_shape, bool p_close){
+
+ if (p_shape.size()<3) {
+ canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape);
+ return;
+ }
+
+ DVector<Vector2> lines;
+ int lc = p_shape.size()*2;
+
+ lines.resize(lc-(p_close?0:2));
+ {
+ DVector<Vector2>::Write w = lines.write();
+ DVector<Vector2>::Read r = p_shape.read();
+
+ int max=lc/2;
+ if (!p_close) {
+ max--;
+ }
+ for(int i=0;i<max;i++) {
+
+ Vector2 a = r[i];
+ Vector2 b = r[(i+1)%(lc/2)];
+ w[i*2+0]=a;
+ w[i*2+1]=b;
+ }
+
+ }
+
+ canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines);
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape) {
+
+ CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ ERR_FAIL_COND(p_shape.size()&1);
+
+ int lc = p_shape.size();
+ occluder_poly->aabb=Rect2();
+ {
+ DVector<Vector2>::Read r = p_shape.read();
+ for(int i=0;i<lc;i++) {
+ if (i==0)
+ occluder_poly->aabb.pos=r[i];
+ else
+ occluder_poly->aabb.expand_to(r[i]);
+ }
+ }
+
+ rasterizer->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape);
+ for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->aabb_cache=occluder_poly->aabb;
+ }
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode) {
+
+ CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->cull_mode=p_mode;
+ for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->cull_cache=p_mode;
+ }
}
-void VisualServerRaster::canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape){
+RID VisualServerRaster::canvas_item_material_create() {
+ Rasterizer::CanvasItemMaterial *material = memnew( Rasterizer::CanvasItemMaterial );
+ return canvas_item_material_owner.make_rid(material);
}
+void VisualServerRaster::canvas_item_material_set_shader(RID p_material, RID p_shader){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ material->shader=p_shader;
+
+}
+void VisualServerRaster::canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ if (p_value.get_type()==Variant::NIL)
+ material->shader_param.erase(p_param);
+ else
+ material->shader_param[p_param]=p_value;
+
+
+}
+Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const{
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND_V(!material,Variant());
+ if (!material->shader_param.has(p_param)) {
+ ERR_FAIL_COND_V(!material->shader.is_valid(),Variant());
+ return rasterizer->shader_get_default_param(material->shader,p_param);
+ }
+
+ return material->shader_param[p_param];
+}
+
+void VisualServerRaster::canvas_item_material_set_unshaded(RID p_material, bool p_unshaded){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ material->unshaded=p_unshaded;
+
+}
/******** CANVAS *********/
@@ -4285,6 +4533,10 @@ void VisualServerRaster::free( RID p_rid ) {
E->get()->canvas=RID();
}
+ for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) {
+
+ E->get()->canvas=RID();
+ }
canvas_owner.free( p_rid );
@@ -4314,10 +4566,26 @@ void VisualServerRaster::free( RID p_rid ) {
canvas_item->child_items[i]->parent=RID();
}
+ if (canvas_item->material) {
+ canvas_item->material->owners.erase(canvas_item);
+ }
+
canvas_item_owner.free( p_rid );
memdelete( canvas_item );
+ } else if (canvas_item_material_owner.owns(p_rid)) {
+
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get(p_rid);
+ ERR_FAIL_COND(!material);
+ for(Set<Rasterizer::CanvasItem*>::Element *E=material->owners.front();E;E=E->next()) {
+
+ E->get()->material=NULL;
+ }
+
+ canvas_item_material_owner.free(p_rid);
+ memdelete(material);
+
} else if (canvas_light_owner.owns(p_rid)) {
Rasterizer::CanvasLight *canvas_light = canvas_light_owner.get(p_rid);
@@ -4329,9 +4597,51 @@ void VisualServerRaster::free( RID p_rid ) {
canvas->lights.erase(canvas_light);
}
+ if (canvas_light->shadow_buffer.is_valid())
+ rasterizer->free(canvas_light->shadow_buffer);
+
canvas_light_owner.free( p_rid );
memdelete( canvas_light );
+ } else if (canvas_light_occluder_owner.owns(p_rid)) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->polygon.is_valid()) {
+
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+
+ }
+
+ if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.erase(occluder);
+
+ }
+
+ canvas_light_occluder_owner.free( p_rid );
+ memdelete(occluder);
+
+ } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
+
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid);
+ ERR_FAIL_COND(!occluder_poly);
+ rasterizer->free(occluder_poly->occluder);
+
+ while(occluder_poly->owners.size()) {
+
+ occluder_poly->owners.front()->get()->polygon=RID();
+ occluder_poly->owners.erase( occluder_poly->owners.front() );
+ }
+
+ canvas_light_occluder_polygon_owner.free( p_rid );
+ memdelete(occluder_poly);
+
} else if (scenario_owner.owns(p_rid)) {
Scenario *scenario=scenario_owner.get(p_rid);
@@ -5976,6 +6286,20 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan
}
+void VisualServerRaster::_render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) {
+ RID environment;
+ if (p_scenario->environment.is_valid())
+ environment=p_scenario->environment;
+ else
+ environment=p_scenario->fallback_environment;
+
+ rasterizer->set_camera(Transform(),CameraMatrix());
+ rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug);
+ rasterizer->set_viewport(viewport_rect);
+ rasterizer->end_scene();
+}
+
+
void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) {
@@ -6410,7 +6734,7 @@ void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void
}
-void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner) {
+void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_material_owner) {
CanvasItem *ci = p_canvas_item;
@@ -6455,11 +6779,11 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
ci->vp_render=NULL;
}
- if (ci->use_parent_shader && p_shader_owner)
- ci->shader_owner=p_shader_owner;
+ if (ci->use_parent_material && p_material_owner)
+ ci->material_owner=p_material_owner;
else {
- p_shader_owner=ci;
- ci->shader_owner=NULL;
+ p_material_owner=ci;
+ ci->material_owner=NULL;
}
@@ -6493,11 +6817,15 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
if (child_items[i]->ontop)
continue;
- _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
}
+ if (ci->copy_back_buffer) {
+
+ ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect);
+ }
- if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render) {
+ if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) {
//something to draw?
ci->final_transform=xform;
ci->final_opacity=opacity * ci->self_opacity;
@@ -6524,7 +6852,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
if (!child_items[i]->ontop)
continue;
- _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
}
}
@@ -6594,6 +6922,23 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans
}
+void VisualServerRaster::_draw_viewport_camera(Viewport *p_viewport,bool p_ignore_camera) {
+
+
+ Camera *camera=NULL;
+ if (camera_owner.owns( p_viewport->camera ))
+ camera=camera_owner.get( p_viewport->camera );
+ Scenario *scenario = scenario_owner.get( p_viewport->scenario );
+
+ _update_instances(); // check dirty instances before rendering
+
+ if (p_ignore_camera)
+ _render_no_camera(p_viewport, camera,scenario );
+ else
+ _render_camera(p_viewport, camera,scenario );
+
+}
+
void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ofs_y,int p_parent_w,int p_parent_h) {
ViewportRect desired_rect=p_viewport->rect;
@@ -6628,20 +6973,45 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
/* Camera should always be BEFORE any other 3D */
- if (!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario)) {
+ bool scenario_draw_canvas_bg=false;
+ int scenario_canvas_max_layer=0;
- Camera *camera = camera_owner.get( p_viewport->camera );
- Scenario *scenario = scenario_owner.get( p_viewport->scenario );
+ if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) {
- _update_instances(); // check dirty instances before rendering
+ Scenario *scenario=scenario_owner.get(p_viewport->scenario);
+ if (scenario->environment.is_valid()) {
+ if (rasterizer->is_environment(scenario->environment)) {
+ scenario_draw_canvas_bg=rasterizer->environment_get_background(scenario->environment)==VS::ENV_BG_CANVAS;
+ scenario_canvas_max_layer=rasterizer->environment_get_background_param(scenario->environment,VS::ENV_BG_PARAM_CANVAS_MAX_LAYER);
+ }
+ }
+ }
- _render_camera(p_viewport, camera,scenario );
+ bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario);
+
+
+ if (scenario_draw_canvas_bg) {
+
+ rasterizer->begin_canvas_bg();
+ }
+
+ if (!scenario_draw_canvas_bg && can_draw_3d) {
+
+ _draw_viewport_camera(p_viewport,false);
} else if (true /*|| !p_viewport->canvas_list.empty()*/){
//clear the viewport black because of no camera? i seriously should..
if (p_viewport->render_target_clear_on_new_frame || p_viewport->render_target_clear) {
- rasterizer->clear_viewport(clear_color);
+ if (p_viewport->transparent_bg) {
+ rasterizer->clear_viewport(Color(0,0,0,0));
+ }
+ else {
+ Color cc=clear_color;
+ if (scenario_draw_canvas_bg)
+ cc.a=0;
+ rasterizer->clear_viewport(cc);
+ }
p_viewport->render_target_clear=false;
}
}
@@ -6653,6 +7023,10 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
Rect2 clip_rect(0,0,viewport_rect.width,viewport_rect.height);
Rasterizer::CanvasLight *lights=NULL;
+ Rasterizer::CanvasLight *lights_with_shadow=NULL;
+ Rect2 shadow_rect;
+
+ int light_count=0;
for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
@@ -6667,10 +7041,12 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
if (cl->enabled && cl->texture.is_valid()) {
//not super efficient..
Size2 tsize(rasterizer->texture_get_width(cl->texture),rasterizer->texture_get_height(cl->texture));
+ tsize*=cl->scale;
Vector2 offset=tsize/2.0;
cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize);
cl->xform_cache=xf * cl->xform;
+
if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) {
cl->filter_next_ptr=lights;
lights=cl;
@@ -6680,15 +7056,67 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
scale.elements[2]=cl->rect_cache.pos;
cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
cl->light_shader_pos=cl->xform_cache[2];
+ if (cl->shadow_buffer.is_valid()) {
+ cl->shadows_next_ptr=lights_with_shadow;
+ if (lights_with_shadow==NULL) {
+ shadow_rect = cl->xform_cache.xform(cl->rect_cache);
+ } else {
+ shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) );
+ }
+ lights_with_shadow=cl;
+ cl->radius_cache=cl->rect_cache.size.length();
+
+ }
+
+ light_count++;
}
+ }
+ }
+
+ //print_line("lights: "+itos(light_count));
+ canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get();
+ }
+ if (lights_with_shadow) {
+ //update shadows if any
+ Rasterizer::CanvasLightOccluderInstance * occluders=NULL;
+ //make list of occluders
+ for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
+
+ Matrix32 xf = p_viewport->global_transform * E->get().transform;
+
+ for(Set<Rasterizer::CanvasLightOccluderInstance*>::Element *F=E->get().canvas->occluders.front();F;F=F->next()) {
+
+ F->get()->xform_cache = xf * F->get()->xform;
+ if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) {
+
+ F->get()->next=occluders;
+ occluders=F->get();
+
+ }
}
}
+ //update the light shadowmaps with them
+ Rasterizer::CanvasLight *light=lights_with_shadow;
+ while(light) {
- canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get();
+ rasterizer->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache);
+ light=light->shadows_next_ptr;
+ }
+
+ rasterizer->set_viewport(viewport_rect); //must reset viewport afterwards
+ }
+
+
+
+
+ if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer>scenario_canvas_max_layer) {
+
+ _draw_viewport_camera(p_viewport,!can_draw_3d);
+ scenario_draw_canvas_bg=false;
}
@@ -6713,7 +7141,21 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
_render_canvas( E->get()->canvas,xform,canvas_lights );
i++;
+ if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) {
+ _draw_viewport_camera(p_viewport,!can_draw_3d);
+ scenario_draw_canvas_bg=false;
+ }
+
+
}
+
+ if (scenario_draw_canvas_bg) {
+ _draw_viewport_camera(p_viewport,!can_draw_3d);
+ scenario_draw_canvas_bg=false;
+ }
+
+
+ //rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
}
//capture
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 9b2b0c9c1a..72af793278 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -371,7 +371,7 @@ class VisualServerRaster : public VisualServer {
-
+ mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner;
struct CanvasItem : public Rasterizer::CanvasItem {
@@ -384,7 +384,7 @@ class VisualServerRaster : public VisualServer {
bool sort_y;
float opacity;
float self_opacity;
- bool use_parent_shader;
+ bool use_parent_material;
Vector<CanvasItem*> child_items;
@@ -396,7 +396,7 @@ class VisualServerRaster : public VisualServer {
opacity=1;
self_opacity=1;
sort_y=false;
- use_parent_shader=false;
+ use_parent_material=false;
z_relative=true;
}
};
@@ -410,6 +410,24 @@ class VisualServerRaster : public VisualServer {
}
};
+ struct CanvasLightOccluder;
+
+ struct CanvasLightOccluderPolygon {
+
+ bool active;
+ Rect2 aabb;
+ CanvasOccluderPolygonCullMode cull_mode;
+ RID occluder;
+ Set<Rasterizer::CanvasLightOccluderInstance*> owners;
+
+ CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+ RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner;
+
+ RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner;
+
struct CanvasLight;
struct Canvas {
@@ -422,6 +440,7 @@ class VisualServerRaster : public VisualServer {
};
Set<Rasterizer::CanvasLight*> lights;
+ Set<Rasterizer::CanvasLightOccluderInstance*> occluders;
Vector<ChildItem> child_items;
Color modulate;
@@ -470,6 +489,8 @@ class VisualServerRaster : public VisualServer {
bool render_target_vflip;
bool render_target_clear_on_new_frame;
bool render_target_clear;
+ bool disable_environment;
+
Image capture;
bool rendered_in_prev_frame;
@@ -496,7 +517,7 @@ class VisualServerRaster : public VisualServer {
SelfList<Viewport> update_list;
- Viewport() : update_list(this) { transparent_bg=false; render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE; queue_capture=false; rendered_in_prev_frame=false; render_target_vflip=false; render_target_clear_on_new_frame=true; render_target_clear=true;}
+ Viewport() : update_list(this) { transparent_bg=false; render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE; queue_capture=false; rendered_in_prev_frame=false; render_target_vflip=false; render_target_clear_on_new_frame=true; render_target_clear=true; disable_environment=false; }
};
SelfList<Viewport>::List viewport_update_list;
@@ -607,10 +628,11 @@ class VisualServerRaster : public VisualServer {
void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL);
void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace);
+ void _render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
- void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner);
+ void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights);
Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
@@ -624,6 +646,7 @@ class VisualServerRaster : public VisualServer {
int changes;
bool draw_extra_frame;
+ void _draw_viewport_camera(Viewport *p_viewport, bool p_ignore_camera);
void _draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ofs_y,int p_parent_w,int p_parent_h);
void _draw_viewports();
void _draw_cursors_and_margins();
@@ -964,6 +987,7 @@ public:
virtual void viewport_render_target_clear(RID p_viewport);
virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect);
+
virtual void viewport_queue_screen_capture(RID p_viewport);
virtual Image viewport_get_screen_capture(RID p_viewport) const;
@@ -972,6 +996,7 @@ public:
virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide);
virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide);
+ virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable);
virtual void viewport_attach_camera(RID p_viewport,RID p_camera);
virtual void viewport_set_scenario(RID p_viewport,RID p_scenario);
@@ -1103,6 +1128,7 @@ public:
//virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect);
virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform);
virtual void canvas_item_set_clip(RID p_item, bool p_clip);
+ virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable);
virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2());
virtual void canvas_item_set_opacity(RID p_item, float p_opacity);
virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const;
@@ -1130,21 +1156,16 @@ public:
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
virtual void canvas_item_set_z(RID p_item, int p_z);
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
+ virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect);
- virtual void canvas_item_set_shader(RID p_item, RID p_shader);
- virtual RID canvas_item_get_shader(RID p_item) const;
-
- virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable);
-
-
-
- virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value);
- virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const;
+ virtual void canvas_item_set_material(RID p_item, RID p_material);
+ virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
virtual RID canvas_light_create();
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas);
virtual void canvas_light_set_enabled(RID p_light, bool p_enabled);
virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform);
+ virtual void canvas_light_set_scale(RID p_light, float p_scale);
virtual void canvas_light_set_texture(RID p_light, RID p_texture);
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset);
virtual void canvas_light_set_color(RID p_light, const Color& p_color);
@@ -1152,21 +1173,41 @@ public:
virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z);
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer);
virtual void canvas_light_set_item_mask(RID p_light, int p_mask);
+ virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask);
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable);
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
- virtual void canvas_light_set_shadow_filter(RID p_light, int p_size);
+ virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier);
virtual RID canvas_light_occluder_create();
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas);
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled);
- virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape);
+ virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon);
+ virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform);
+ virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask);
+
+
+ virtual RID canvas_occluder_polygon_create();
+ virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_close);
+ virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape);
+ virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode);
+
+
virtual void canvas_item_clear(RID p_item);
virtual void canvas_item_raise(RID p_item);
+ /* CANVAS ITEM MATERIAL */
+
+ virtual RID canvas_item_material_create();
+ virtual void canvas_item_material_set_shader(RID p_material, RID p_shader);
+ virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value);
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
+ virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded);
+
+
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians
virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 6c95b6ed58..ded4c6fc00 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -982,6 +982,7 @@ public:
FUNC2(viewport_set_hide_canvas,RID,bool );
FUNC2(viewport_attach_camera,RID,RID );
FUNC2(viewport_set_scenario,RID,RID );
+ FUNC2(viewport_set_disable_environment,RID,bool );
FUNC1RC(RID,viewport_get_attached_camera,RID);
FUNC1RC(RID,viewport_get_scenario,RID );
@@ -1108,6 +1109,7 @@ public:
//FUNC(canvas_item_set_rect,RID, const Rect2& p_rect);
FUNC2(canvas_item_set_transform,RID, const Matrix32& );
FUNC2(canvas_item_set_clip,RID, bool );
+ FUNC2(canvas_item_set_distance_field_mode,RID, bool );
FUNC3(canvas_item_set_custom_rect,RID, bool ,const Rect2&);
FUNC2(canvas_item_set_opacity,RID, float );
FUNC2RC(float,canvas_item_get_opacity,RID, float );
@@ -1138,15 +1140,12 @@ public:
FUNC2(canvas_item_set_sort_children_by_y,RID,bool);
FUNC2(canvas_item_set_z,RID,int);
FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
+ FUNC3(canvas_item_set_copy_to_backbuffer,RID,bool,const Rect2&);
- FUNC2(canvas_item_set_shader,RID, RID );
- FUNC1RC(RID,canvas_item_get_shader,RID );
- FUNC2(canvas_item_set_use_parent_shader,RID, bool );
+ FUNC2(canvas_item_set_material,RID, RID );
-
- FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&);
- FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_set_use_parent_material,RID, bool );
FUNC1(canvas_item_clear,RID);
FUNC1(canvas_item_raise,RID);
@@ -1156,6 +1155,7 @@ public:
FUNC2(canvas_light_attach_to_canvas,RID,RID);
FUNC2(canvas_light_set_enabled,RID,bool);
FUNC2(canvas_light_set_transform,RID,const Matrix32&);
+ FUNC2(canvas_light_set_scale,RID,float);
FUNC2(canvas_light_set_texture,RID,RID);
FUNC2(canvas_light_set_texture_offset,RID,const Vector2&);
FUNC2(canvas_light_set_color,RID,const Color&);
@@ -1163,18 +1163,36 @@ public:
FUNC3(canvas_light_set_layer_range,RID,int,int);
FUNC3(canvas_light_set_z_range,RID,int,int);
FUNC2(canvas_light_set_item_mask,RID,int);
+ FUNC2(canvas_light_set_item_shadow_mask,RID,int);
FUNC2(canvas_light_set_subtract_mode,RID,bool);
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
- FUNC2(canvas_light_set_shadow_filter,RID,int);
+ FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float);
+
/* CANVAS OCCLUDER */
FUNC0R(RID,canvas_light_occluder_create);
FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID);
FUNC2(canvas_light_occluder_set_enabled,RID,bool);
- FUNC2(canvas_light_occluder_set_shape,RID,const DVector<Vector2>&);
+ FUNC2(canvas_light_occluder_set_polygon,RID,RID);
+ FUNC2(canvas_light_occluder_set_transform,RID,const Matrix32&);
+ FUNC2(canvas_light_occluder_set_light_mask,RID,int);
+
+
+ FUNC0R(RID,canvas_occluder_polygon_create);
+ FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>&,bool);
+ FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&);
+ FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode);
+
+ /* CANVAS MATERIAL */
+
+ FUNC0R(RID,canvas_item_material_create);
+ FUNC2(canvas_item_material_set_shader,RID,RID);
+ FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&);
+ FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_material_set_unshaded,RID,bool);
/* CURSOR */
FUNC2(cursor_set_rotation,float , int ); // radians
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 37368e32f4..b6d354454e 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -704,6 +704,7 @@ public:
virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide)=0;
virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide)=0;
+ virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable)=0;
virtual void viewport_attach_camera(RID p_viewport,RID p_camera)=0;
virtual void viewport_set_scenario(RID p_viewport,RID p_scenario)=0;
@@ -734,8 +735,7 @@ public:
ENV_BG_COLOR,
ENV_BG_TEXTURE,
ENV_BG_CUBEMAP,
- ENV_BG_TEXTURE_RGBE,
- ENV_BG_CUBEMAP_RGBE,
+ ENV_BG_CANVAS,
ENV_BG_MAX
};
@@ -744,6 +744,7 @@ public:
enum EnvironmentBGParam {
+ ENV_BG_PARAM_CANVAS_MAX_LAYER,
ENV_BG_PARAM_COLOR,
ENV_BG_PARAM_TEXTURE,
ENV_BG_PARAM_CUBEMAP,
@@ -968,6 +969,7 @@ public:
virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform)=0;
virtual void canvas_item_set_clip(RID p_item, bool p_clip)=0;
+ virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable)=0;
virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2())=0;
virtual void canvas_item_set_opacity(RID p_item, float p_opacity)=0;
virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const=0;
@@ -994,21 +996,19 @@ public:
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0;
virtual void canvas_item_set_z(RID p_item, int p_z)=0;
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable)=0;
+ virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect)=0;
virtual void canvas_item_clear(RID p_item)=0;
virtual void canvas_item_raise(RID p_item)=0;
- virtual void canvas_item_set_shader(RID p_item, RID p_shader)=0;
- virtual RID canvas_item_get_shader(RID p_item) const=0;
+ virtual void canvas_item_set_material(RID p_item, RID p_material)=0;
- virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable)=0;
-
- virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0;
- virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=0;
+ virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable)=0;
virtual RID canvas_light_create()=0;
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0;
virtual void canvas_light_set_enabled(RID p_light, bool p_enabled)=0;
+ virtual void canvas_light_set_scale(RID p_light, float p_scale)=0;
virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform)=0;
virtual void canvas_light_set_texture(RID p_light, RID p_texture)=0;
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset)=0;
@@ -1017,17 +1017,39 @@ public:
virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0;
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0;
virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0;
+ virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0;
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0;
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0;
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0;
- virtual void canvas_light_set_shadow_filter(RID p_light, int p_size)=0;
+ virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0;
+
virtual RID canvas_light_occluder_create()=0;
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0;
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0;
- virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape)=0;
+ virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon)=0;
+ virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform)=0;
+ virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask)=0;
+
+ virtual RID canvas_occluder_polygon_create()=0;
+ virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed)=0;
+ virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape)=0;
+ enum CanvasOccluderPolygonCullMode {
+ CANVAS_OCCLUDER_POLYGON_CULL_DISABLED,
+ CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE,
+ CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE,
+ };
+ virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0;
+
+ /* CANVAS ITEM MATERIAL */
+
+ virtual RID canvas_item_material_create()=0;
+ virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0;
+ virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0;
+ virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded)=0;
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
diff --git a/tools/collada/collada.cpp b/tools/collada/collada.cpp
index 97e9f5c36d..b55edde801 100644
--- a/tools/collada/collada.cpp
+++ b/tools/collada/collada.cpp
@@ -817,7 +817,7 @@ void Collada::_parse_camera(XMLParser& parser) {
if (name=="perspective") {
camera.mode=CameraData::MODE_PERSPECTIVE;
- } else if (name=="orthogonal") {
+ } else if (name=="orthographic") {
camera.mode=CameraData::MODE_ORTHOGONAL;
} else if (name=="xfov") {
diff --git a/tools/collada/collada.h b/tools/collada/collada.h
index f523d24e02..7691d90c0a 100644
--- a/tools/collada/collada.h
+++ b/tools/collada/collada.h
@@ -337,6 +337,24 @@ public:
if(normal==p_vert.normal) {
if(uv==p_vert.uv) {
if(uv2==p_vert.uv2) {
+
+ if (!weights.empty() || !p_vert.weights.empty()) {
+
+ if (weights.size()==p_vert.weights.size()) {
+
+ for(int i=0;i<weights.size();i++) {
+ if (weights[i].bone_idx!=p_vert.weights[i].bone_idx)
+ return weights[i].bone_idx<p_vert.weights[i].bone_idx;
+
+ if (weights[i].weight!=p_vert.weights[i].weight)
+ return weights[i].weight<p_vert.weights[i].weight;
+ }
+ } else {
+ return weights.size() < p_vert.weights.size();
+ }
+
+ }
+
return (color<p_vert.color);
} else
return (uv2<p_vert.uv2);
diff --git a/tools/editor/connections_dialog.cpp b/tools/editor/connections_dialog.cpp
index d7158eb7e9..cf4b21510a 100644
--- a/tools/editor/connections_dialog.cpp
+++ b/tools/editor/connections_dialog.cpp
@@ -607,6 +607,14 @@ void ConnectionsDialog::_remove_confirm() {
}
*/
+
+struct _ConnectionsDialogMethodInfoSort {
+
+ _FORCE_INLINE_ bool operator()(const MethodInfo& a, const MethodInfo& b) const {
+ return a.name < b.name;
+ }
+};
+
void ConnectionsDialog::update_tree() {
if (!is_visible())
@@ -623,7 +631,8 @@ void ConnectionsDialog::update_tree() {
node->get_signal_list(&node_signals);
-
+ //node_signals.sort_custom<_ConnectionsDialogMethodInfoSort>();
+
for(List<MethodInfo>::Element *E=node_signals.front();E;E=E->next()) {
diff --git a/tools/editor/editor_dir_dialog.cpp b/tools/editor/editor_dir_dialog.cpp
index eee4125e93..eec452ab7f 100644
--- a/tools/editor/editor_dir_dialog.cpp
+++ b/tools/editor/editor_dir_dialog.cpp
@@ -28,6 +28,9 @@
/*************************************************************************/
#include "editor_dir_dialog.h"
#include "os/os.h"
+#include "os/keyboard.h"
+#include "tools/editor/editor_settings.h"
+
void EditorDirDialog::_update_dir(TreeItem* p_item) {
@@ -39,12 +42,21 @@ void EditorDirDialog::_update_dir(TreeItem* p_item) {
da->change_dir(cdir);
da->list_dir_begin();
String p=da->get_next();
+
+ bool ishidden;
+ bool show_hidden = EditorSettings::get_singleton()->get("file_dialog/show_hidden_files");
+
while(p!="") {
- if (da->current_is_dir() && !p.begins_with(".")) {
- TreeItem *ti = tree->create_item(p_item);
- ti->set_text(0,p);
- ti->set_icon(0,get_icon("Folder","EditorIcons"));
- ti->set_collapsed(true);
+
+ ishidden = da->current_is_hidden();
+
+ if (show_hidden || !ishidden) {
+ if (da->current_is_dir() && !p.begins_with(".")) {
+ TreeItem *ti = tree->create_item(p_item);
+ ti->set_text(0,p);
+ ti->set_icon(0,get_icon("Folder","EditorIcons"));
+ ti->set_collapsed(true);
+ }
}
p=da->get_next();
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
index 6399d0f909..e6ec11e9d3 100644
--- a/tools/editor/editor_import_export.cpp
+++ b/tools/editor/editor_import_export.cpp
@@ -904,6 +904,16 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func
return OK;
}
+static int _get_pad(int p_alignment, int p_n) {
+
+ int rest = p_n % p_alignment;
+ int pad = 0;
+ if (rest > 0) {
+ pad = p_alignment - rest;
+ };
+
+ return pad;
+};
Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
@@ -930,11 +940,19 @@ Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path
pd->ep->step("Storing File: "+p_path,2+p_file*100/p_total);
pd->count++;
pd->ftmp->store_buffer(p_data.ptr(),p_data.size());
+ if (pd->alignment > 1) {
+
+ int pad = _get_pad(pd->alignment, pd->ftmp->get_pos());
+ for (int i=0; i<pad; i++) {
+
+ pd->ftmp->store_8(0);
+ };
+ };
return OK;
}
-Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
+Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles, int p_alignment) {
EditorProgress ep("savepack","Packing",102);
@@ -952,7 +970,6 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
dst->store_32(0);
}
-
size_t fcountpos = dst->get_pos();
dst->store_32(0);
@@ -961,11 +978,20 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
pd.f=dst;
pd.ftmp=tmp;
pd.count=0;
+ pd.alignment = p_alignment;
Error err = export_project_files(save_pack_file,&pd,p_make_bundles);
memdelete(tmp);
if (err)
return err;
+ if (p_alignment > 1) {
+ int pad = _get_pad(p_alignment, dst->get_pos());
+ for (int i=0; i<pad; i++) {
+
+ dst->store_8(0);
+ };
+ };
+
size_t ofsplus = dst->get_pos();
//append file
diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h
index cd24fa076b..a4723f41d0 100644
--- a/tools/editor/editor_import_export.h
+++ b/tools/editor/editor_import_export.h
@@ -100,6 +100,7 @@ protected:
Vector<TempData> file_ofs;
EditorProgress *ep;
int count;
+ int alignment;
};
@@ -121,7 +122,7 @@ public:
Error export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles);
- Error save_pack(FileAccess *p_where, bool p_make_bundles=false);
+ Error save_pack(FileAccess *p_where, bool p_make_bundles=false, int p_alignment = 1);
virtual String get_name() const =0;
virtual ImageCompression get_image_compression() const=0;
virtual Ref<Texture> get_logo() const =0;
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index cc1a05f7d3..5e571373ea 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -90,6 +90,7 @@
#include "plugins/baked_light_editor_plugin.h"
#include "plugins/polygon_2d_editor_plugin.h"
#include "plugins/navigation_polygon_editor_plugin.h"
+#include "plugins/light_occluder_2d_editor_plugin.h"
// end
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
@@ -217,6 +218,7 @@ void EditorNode::_notification(int p_what) {
}
if (p_what==NOTIFICATION_ENTER_TREE) {
+
//MessageQueue::get_singleton()->push_call(this,"_get_scene_metadata");
get_tree()->set_editor_hint(true);
get_tree()->get_root()->set_as_audio_listener(false);
@@ -230,6 +232,8 @@ void EditorNode::_notification(int p_what) {
VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport(),true);
VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport(),true);
+ VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(),true);
+
_editor_select(1);
if (defer_load_scene!="") {
@@ -3411,6 +3415,8 @@ EditorNode::EditorNode() {
scene_root = memnew( Viewport );
+
+
//scene_root_base->add_child(scene_root);
scene_root->set_meta("_editor_disable_input",true);
VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport(),true);
@@ -4115,6 +4121,7 @@ EditorNode::EditorNode() {
add_editor_plugin( memnew( PathEditorPlugin(this) ) );
add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) );
add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
+ add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) );
add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
for(int i=0;i<EditorPlugins::get_plugin_count();i++)
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 24699ac87f..deb5d86a2e 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -446,6 +446,7 @@ void EditorSettings::_load_defaults() {
set("text_editor/create_signal_callbacks",true);
+ set("file_dialog/show_hidden_files", false);
set("animation/autorename_animation_tracks",true);
set("animation/confirm_insert_track",true);
diff --git a/tools/editor/icons/icon_back_buffer_copy.png b/tools/editor/icons/icon_back_buffer_copy.png
new file mode 100644
index 0000000000..b27eb39108
--- /dev/null
+++ b/tools/editor/icons/icon_back_buffer_copy.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_item_material.png b/tools/editor/icons/icon_canvas_item_material.png
new file mode 100644
index 0000000000..2fe8921653
--- /dev/null
+++ b/tools/editor/icons/icon_canvas_item_material.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_modulate.png b/tools/editor/icons/icon_canvas_modulate.png
new file mode 100644
index 0000000000..2a34df7793
--- /dev/null
+++ b/tools/editor/icons/icon_canvas_modulate.png
Binary files differ
diff --git a/tools/editor/icons/icon_check_box.png b/tools/editor/icons/icon_check_box.png
new file mode 100644
index 0000000000..8a2b56cc3e
--- /dev/null
+++ b/tools/editor/icons/icon_check_box.png
Binary files differ
diff --git a/tools/editor/icons/icon_light_occluder_2d.png b/tools/editor/icons/icon_light_occluder_2d.png
new file mode 100644
index 0000000000..c66dd536d3
--- /dev/null
+++ b/tools/editor/icons/icon_light_occluder_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_occluder_polygon_2d.png b/tools/editor/icons/icon_occluder_polygon_2d.png
new file mode 100644
index 0000000000..705794b729
--- /dev/null
+++ b/tools/editor/icons/icon_occluder_polygon_2d.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 1fd7d26f8b..0562153199 100644
--- a/tools/editor/io_plugins/editor_font_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp
@@ -47,6 +47,12 @@ class _EditorFontImportOptions : public Object {
OBJ_TYPE(_EditorFontImportOptions,Object);
public:
+ enum FontMode {
+
+ FONT_BITMAP,
+ FONT_DISTANCE_FIELD
+ };
+
enum ColorType {
COLOR_WHITE,
COLOR_CUSTOM,
@@ -69,6 +75,9 @@ public:
CHARSET_CUSTOM_LATIN
};
+
+ FontMode font_mode;
+
CharacterSet character_set;
String custom_file;
@@ -91,7 +100,6 @@ public:
bool color_use_monochrome;
String gradient_image;
-
bool disable_filter;
bool round_advance;
@@ -100,7 +108,10 @@ public:
bool _set(const StringName& p_name, const Variant& p_value) {
String n = p_name;
- if (n=="extra_space/char")
+ if (n=="mode/mode") {
+ font_mode=FontMode(int(p_value));
+ _change_notify();
+ } else if (n=="extra_space/char")
char_extra_spacing=p_value;
else if (n=="extra_space/space")
space_extra_spacing=p_value;
@@ -169,7 +180,9 @@ public:
bool _get(const StringName& p_name,Variant &r_ret) const{
String n = p_name;
- if (n=="extra_space/char")
+ if (n=="mode/mode")
+ r_ret=font_mode;
+ else if (n=="extra_space/char")
r_ret=char_extra_spacing;
else if (n=="extra_space/space")
r_ret=space_extra_spacing;
@@ -231,6 +244,9 @@ public:
void _get_property_list( List<PropertyInfo> *p_list) const{
+
+ p_list->push_back(PropertyInfo(Variant::INT,"mode/mode",PROPERTY_HINT_ENUM,"Bitmap,Distance Field"));
+
p_list->push_back(PropertyInfo(Variant::INT,"extra_space/char",PROPERTY_HINT_RANGE,"-64,64,1"));
p_list->push_back(PropertyInfo(Variant::INT,"extra_space/space",PROPERTY_HINT_RANGE,"-64,64,1"));
p_list->push_back(PropertyInfo(Variant::INT,"extra_space/top",PROPERTY_HINT_RANGE,"-64,64,1"));
@@ -240,35 +256,45 @@ public:
if (character_set>=CHARSET_CUSTOM)
p_list->push_back(PropertyInfo(Variant::STRING,"character_set/custom",PROPERTY_HINT_FILE));
- p_list->push_back(PropertyInfo(Variant::BOOL,"shadow/enabled"));
- if (shadow) {
- p_list->push_back(PropertyInfo(Variant::INT,"shadow/radius",PROPERTY_HINT_RANGE,"-64,64,1"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow/offset"));
- p_list->push_back(PropertyInfo(Variant::COLOR,"shadow/color"));
- p_list->push_back(PropertyInfo(Variant::REAL,"shadow/transition",PROPERTY_HINT_EXP_EASING));
- }
+ int usage = PROPERTY_USAGE_DEFAULT;
- p_list->push_back(PropertyInfo(Variant::BOOL,"shadow2/enabled"));
- if (shadow2) {
- p_list->push_back(PropertyInfo(Variant::INT,"shadow2/radius",PROPERTY_HINT_RANGE,"-64,64,1"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow2/offset"));
- p_list->push_back(PropertyInfo(Variant::COLOR,"shadow2/color"));
- p_list->push_back(PropertyInfo(Variant::REAL,"shadow2/transition",PROPERTY_HINT_EXP_EASING));
+ if (font_mode==FONT_DISTANCE_FIELD) {
+ usage = PROPERTY_USAGE_NOEDITOR;
}
- p_list->push_back(PropertyInfo(Variant::INT,"color/mode",PROPERTY_HINT_ENUM,"White,Color,Gradient,Gradient Image"));
- if (color_type==COLOR_CUSTOM) {
- p_list->push_back(PropertyInfo(Variant::COLOR,"color/color"));
+ {
+ p_list->push_back(PropertyInfo(Variant::BOOL,"shadow/enabled",PROPERTY_HINT_NONE,"",usage));
+ if (shadow) {
+ p_list->push_back(PropertyInfo(Variant::INT,"shadow/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow/offset",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::COLOR,"shadow/color",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::REAL,"shadow/transition",PROPERTY_HINT_EXP_EASING,"",usage));
+ }
+
+ p_list->push_back(PropertyInfo(Variant::BOOL,"shadow2/enabled",PROPERTY_HINT_NONE,"",usage));
+ if (shadow2) {
+ p_list->push_back(PropertyInfo(Variant::INT,"shadow2/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow2/offset",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::COLOR,"shadow2/color",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::REAL,"shadow2/transition",PROPERTY_HINT_EXP_EASING,"",usage));
+ }
+
+ p_list->push_back(PropertyInfo(Variant::INT,"color/mode",PROPERTY_HINT_ENUM,"White,Color,Gradient,Gradient Image",usage));
+ if (color_type==COLOR_CUSTOM) {
+ p_list->push_back(PropertyInfo(Variant::COLOR,"color/color",PROPERTY_HINT_NONE,"",usage));
+
+ }
+ if (color_type==COLOR_GRADIENT_RANGE) {
+ p_list->push_back(PropertyInfo(Variant::COLOR,"color/begin",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::COLOR,"color/end",PROPERTY_HINT_NONE,"",usage));
+ }
+ if (color_type==COLOR_GRADIENT_IMAGE) {
+ p_list->push_back(PropertyInfo(Variant::STRING,"color/image",PROPERTY_HINT_FILE,"",usage));
+ }
+ p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome",PROPERTY_HINT_NONE,"",usage));
}
- if (color_type==COLOR_GRADIENT_RANGE) {
- p_list->push_back(PropertyInfo(Variant::COLOR,"color/begin"));
- p_list->push_back(PropertyInfo(Variant::COLOR,"color/end"));
- }
- if (color_type==COLOR_GRADIENT_IMAGE) {
- p_list->push_back(PropertyInfo(Variant::STRING,"color/image",PROPERTY_HINT_FILE));
- }
- p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome"));
+
p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/round_advance"));
p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/disable_filter"));
@@ -307,6 +333,7 @@ public:
gradient_end=Color(0.5,0.5,0.5,1);
color_use_monochrome=false;
+ font_mode=FONT_BITMAP;
round_advance=true;
disable_filter=false;
@@ -314,6 +341,8 @@ public:
_EditorFontImportOptions() {
+ font_mode=FONT_BITMAP;
+
char_extra_spacing=0;
top_extra_spacing=0;
bottom_extra_spacing=0;
@@ -706,6 +735,137 @@ struct _EditorKerningKey {
};
+
+static unsigned char get_SDF_radial(
+ unsigned char *fontmap,
+ int w, int h,
+ int x, int y,
+ int max_radius )
+{
+ // hideous brute force method
+ float d2 = max_radius*max_radius+1.0;
+ unsigned char v = fontmap[x+y*w];
+ for( int radius = 1; (radius <= max_radius) && (radius*radius < d2); ++radius )
+ {
+ int line, lo, hi;
+ // north
+ line = y - radius;
+ if( (line >= 0) && (line < h) )
+ {
+ lo = x - radius;
+ hi = x + radius;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= w ) { hi = w-1; }
+ int idx = line * w + lo;
+ for( int i = lo; i <= hi; ++i )
+ {
+ // check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = i - x;
+ float ny = line - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ // move on
+ ++idx;
+ }
+ }
+ // south
+ line = y + radius;
+ if( (line >= 0) && (line < h) )
+ {
+ lo = x - radius;
+ hi = x + radius;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= w ) { hi = w-1; }
+ int idx = line * w + lo;
+ for( int i = lo; i <= hi; ++i )
+ {
+ // check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = i - x;
+ float ny = line - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ // move on
+ ++idx;
+ }
+ }
+ // west
+ line = x - radius;
+ if( (line >= 0) && (line < w) )
+ {
+ lo = y - radius + 1;
+ hi = y + radius - 1;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= h ) { hi = h-1; }
+ int idx = lo * w + line;
+ for( int i = lo; i <= hi; ++i )
+ {
+ // check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = line - x;
+ float ny = i - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ // move on
+ idx += w;
+ }
+ }
+ // east
+ line = x + radius;
+ if( (line >= 0) && (line < w) )
+ {
+ lo = y - radius + 1;
+ hi = y + radius - 1;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= h ) { hi = h-1; }
+ int idx = lo * w + line;
+ for( int i = lo; i <= hi; ++i )
+ {
+ // check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = line - x;
+ float ny = i - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ // move on
+ idx += w;
+ }
+ }
+ }
+ d2 = sqrtf( d2 );
+ if( v==0 )
+ {
+ d2 = -d2;
+ }
+ d2 *= 127.5 / max_radius;
+ d2 += 127.5;
+ if( d2 < 0.0 ) d2 = 0.0;
+ if( d2 > 255.0 ) d2 = 255.0;
+ return (unsigned char)(d2 + 0.5);
+}
+
+
Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata>& p_from, const String &p_existing) {
Ref<ResourceImportMetadata> from = p_from;
@@ -754,7 +914,11 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
}
- error = FT_Set_Pixel_Sizes(face,0,size);
+ int font_mode = from->get_option("mode/mode");
+
+ int scaler=(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD)?16:1;
+
+ error = FT_Set_Pixel_Sizes(face,0,size*scaler);
FT_GlyphSlot slot = face->glyph;
@@ -820,9 +984,9 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
{
bool skip=false;
- error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );
+ error = FT_Load_Char( face, charcode, font_mode==_EditorFontImportOptions::FONT_BITMAP?FT_LOAD_RENDER:FT_LOAD_MONOCHROME );
if (error) skip=true;
- else error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
+ else error = FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono );
if (error) {
skip=true;
} else if (!skip) {
@@ -847,28 +1011,36 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
}
_EditorFontData * fdata = memnew( _EditorFontData );
- fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows );
- fdata->width=slot->bitmap.width;
- fdata->height=slot->bitmap.rows;
- fdata->character=charcode;
- fdata->glyph=FT_Get_Char_Index(face,charcode);
- if (charcode=='x')
- xsize=slot->bitmap.width;
- if (charcode<127) {
- if (slot->bitmap_top>max_up) {
+ int w = slot->bitmap.width;
+ int h = slot->bitmap.rows;
+ int p = slot->bitmap.pitch;
- max_up=slot->bitmap_top;
- }
+ print_line("W: "+itos(w)+" P: "+itos(slot->bitmap.pitch));
+ if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
- if ( (slot->bitmap_top - fdata->height)<max_down ) {
+ // oversize the holding buffer so I can smooth it!
+ int sw = w + scaler * 4;
+ int sh = h + scaler * 4;
+ // do the SDF
+ int sdfw = sw / scaler;
+ int sdfh = sh / scaler;
- max_down=slot->bitmap_top - fdata->height;
- }
+ fdata->width=sdfw;
+ fdata->height=sdfh;
+ } else {
+ fdata->width=w;
+ fdata->height=h;
}
+ fdata->character=charcode;
+ fdata->glyph=FT_Get_Char_Index(face,charcode);
+ if (charcode=='x')
+ xsize=w/scaler;
+
+
fdata->valign=slot->bitmap_top;
fdata->halign=slot->bitmap_left;
@@ -878,12 +1050,85 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
else
fdata->advance=slot->advance.x/float(1<<6);
+ if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
+
+ fdata->halign = fdata->halign / scaler - 1.5;
+ fdata->valign = fdata->valign / scaler + 1.5;
+ fdata->advance/=scaler;
+
+ }
+
fdata->advance+=font_spacing;
- for (int i=0;i<slot->bitmap.width;i++) {
- for (int j=0;j<slot->bitmap.rows;j++) {
- fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
+ if (charcode<127) {
+ int top = fdata->valign;
+ int hmax = h/scaler;
+
+ if (top>max_up) {
+
+ max_up=top;
+ }
+
+
+ if ( (top - hmax)<max_down ) {
+
+ max_down=top - hmax;
+ }
+ }
+
+ if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
+
+
+ // oversize the holding buffer so I can smooth it!
+ int sw = w + scaler * 4;
+ int sh = h + scaler * 4;
+
+ unsigned char *smooth_buf = new unsigned char[sw*sh];
+
+ for( int i = 0; i < sw*sh; ++i ) {
+ smooth_buf[i] = 0;
+ }
+
+ // copy the glyph into the buffer to be smoothed
+ unsigned char *buf = slot->bitmap.buffer;
+ for( int j = 0; j < h; ++j ) {
+ for( int i = 0; i < w; ++i ) {
+ smooth_buf[scaler*2+i+(j+scaler*2)*sw] = 255 * ((buf[j*p+(i>>3)] >> (7 - (i & 7))) & 1);
+ }
+ }
+
+ // do the SDF
+ int sdfw = fdata->width;
+ int sdfh = fdata->height;
+
+ fdata->bitmap.resize( sdfw*sdfh );
+
+ for( int j = 0; j < sdfh; ++j ) {
+ for( int i = 0; i < sdfw; ++i ) {
+ int pd_idx = j*sdfw+i;
+
+ //fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
+
+ fdata->bitmap[pd_idx] =
+ //get_SDF
+ get_SDF_radial
+ ( smooth_buf, sw, sh,
+ i*scaler + (scaler >>1), j*scaler + (scaler >>1),
+ 2*scaler );
+
+ }
+ }
+
+ delete [] smooth_buf;
+
+ } else {
+ fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows );
+ for (int i=0;i<slot->bitmap.width;i++) {
+ for (int j=0;j<slot->bitmap.rows;j++) {
+
+ fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
+ }
}
}
@@ -904,9 +1149,10 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
spd->ofs_x=0;
spd->ofs_y=0;
- if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, ft_render_mode_normal )) {
+ if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono )) {
spd->advance = slot->advance.x>>6; //round to nearest or store as float
+ spd->advance/=scaler;
spd->advance+=font_spacing;
} else {
@@ -955,7 +1201,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
if (kern==0)
continue;
- kerning_map[kpk]=kern;
+ kerning_map[kpk]=kern/scaler;
}
}
}
@@ -1079,7 +1325,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
pixels.resize(s.x*s.y*4);
DVector<uint8_t>::Write w = pixels.write();
- print_line("val: "+itos(font_data_list[i]->valign));
+ //print_line("val: "+itos(font_data_list[i]->valign));
for(int y=0;y<s.height;y++) {
int yc=CLAMP(y-o.y+font_data_list[i]->valign,0,height-1);
@@ -1284,6 +1530,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
font->clear();
font->set_height(height+bottom_space+top_space);
font->set_ascent(ascent+top_space);
+ font->set_distance_field_hint(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD);
//register texures
{
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index 529ed3374b..d2c9f395d2 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -285,13 +285,16 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
case Collada::CameraData::MODE_ORTHOGONAL: {
- if (cd.orthogonal.x_mag) {
+ if (cd.orthogonal.y_mag) {
- camera->set_orthogonal(cd.orthogonal.x_mag,cd.z_near,cd.z_far);
+ camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT);
+ camera->set_orthogonal(cd.orthogonal.y_mag*2.0 ,cd.z_near,cd.z_far);
- } else if (!cd.orthogonal.x_mag && cd.orthogonal.y_mag) {
+ } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) {
- camera->set_orthogonal(cd.orthogonal.y_mag * cd.aspect,cd.z_near,cd.z_far);
+
+ camera->set_keep_aspect_mode(Camera::KEEP_WIDTH);
+ camera->set_orthogonal(cd.orthogonal.x_mag*2.0,cd.z_near,cd.z_far);
}
} break;
@@ -1354,8 +1357,60 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co
vertw = DVector<Vector3>::Write();
DVector<Vector3> normals;
DVector<float> tangents;
+ if(md.vertices[vertex_src_id].sources.has("NORMAL")){
+ //has normals
+ normals.resize(vlen);
+ std::cout << "has normals" << std::endl;
+ String normal_src_id = md.vertices[vertex_src_id].sources["NORMAL"];
+ std::cout << "normals source: "<< normal_src_id.utf8().get_data() <<std::endl;
+ ERR_FAIL_COND_V(!md.sources.has(normal_src_id),ERR_INVALID_DATA);
+
+ const Collada::MeshData::Source *m=&md.sources[normal_src_id];
+
+ ERR_FAIL_COND_V( m->array.size() != vertex_src->array.size(), ERR_INVALID_DATA);
+ int stride=m->stride;
+ if (stride==0)
+ stride=3;
+
+
+ //read normals from morph target
+ DVector<Vector3>::Write vertw = normals.write();
+
+ for(int m_i=0;m_i<m->array.size()/stride;m_i++) {
+
+ int pos = m_i*stride;
+ Vector3 vtx( m->array[pos+0], m->array[pos+1], m->array[pos+2] );
+
+ #ifndef NO_UP_AXIS_SWAP
+ if (collada.state.up_axis==Vector3::AXIS_Z) {
+
+ SWAP( vtx.z, vtx.y );
+ vtx.z = -vtx.z;
+
+ }
+ #endif
- _generate_normals(index_array,vertices,normals);
+ Collada::Vertex vertex;
+ vertex.vertex=vtx;
+ vertex.fix_unit_scale(collada);
+ vtx=vertex.vertex;
+
+ vtx = p_local_xform.xform(vtx);
+
+
+ if (vertex_map.has(m_i)) { //vertex may no longer be here, don't bother converting
+
+
+ for (Set<int> ::Element *E=vertex_map[m_i].front() ; E; E=E->next() ) {
+
+ vertw[E->get()]=vtx;
+ }
+ }
+ }
+
+ }else{
+ _generate_normals(index_array,vertices,normals);//no normals
+ }
if (final_tangent_array.size() && final_uv_array.size()) {
_generate_tangents_and_binormals(index_array,vertices,final_uv_array,normals,tangents);
diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp
index 42a185b7c2..184f80a1b7 100644
--- a/tools/editor/plugins/baked_light_baker.cpp
+++ b/tools/editor/plugins/baked_light_baker.cpp
@@ -1233,7 +1233,7 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c
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);
- skip-true;
+ skip=true;
} else {
diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index 4c3315ad53..a533c6aa1e 100644
--- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -4,6 +4,7 @@
#include "os/file_access.h"
#include "tools/editor/editor_settings.h"
+
void CollisionPolygon2DEditor::_notification(int p_what) {
switch(p_what) {
@@ -357,6 +358,7 @@ void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) {
wip.clear();
wip_active=false;
edited_point=-1;
+ canvas_item_editor->get_viewport_control()->update();
} else {
node=NULL;
diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..5fa3d8ac8f
--- /dev/null
+++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
@@ -0,0 +1,502 @@
+#include "light_occluder_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "tools/editor/editor_settings.h"
+
+void LightOccluder2DEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon( get_icon("Edit","EditorIcons"));
+ button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ button_edit->set_pressed(true);
+ get_tree()->connect("node_removed",this,"_node_removed");
+ create_poly->connect("confirmed",this,"_create_poly");
+
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void LightOccluder2DEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
+}
+
+
+Vector2 LightOccluder2DEditor::snap_point(const Vector2& p_point) const {
+
+ if (canvas_item_editor->is_snap_active()) {
+
+ return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
+
+ } else {
+ return p_point;
+ }
+}
+
+void LightOccluder2DEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case MODE_CREATE: {
+
+ mode=MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode=MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+
+ }
+}
+
+void LightOccluder2DEditor::_wip_close(bool p_closed) {
+
+ undo_redo->create_action("Create Poly");
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",node->get_occluder_polygon()->get_polygon());
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",wip);
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_closed",node->get_occluder_polygon()->is_closed());
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_closed",p_closed);
+
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ wip.clear();
+ wip_active=false;
+ mode=MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ edited_point=-1;
+}
+
+bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
+
+
+ if (!node)
+ return false;
+
+ if (node->get_occluder_polygon().is_null()) {
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+ create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?");
+ create_poly->popup_centered_minsize();
+ }
+ return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);
+ }
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=snap_point(cpoint);
+ cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8);
+
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( cpoint );
+ wip_active=true;
+ edited_point_pos=cpoint;
+ canvas_item_editor->get_viewport_control()->update();
+ edited_point=1;
+ return true;
+ } else {
+
+
+ if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close(true);
+
+ return true;
+ } else if (wip.size()>1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close(false);
+ return true;
+
+ } else {
+
+ wip.push_back( cpoint );
+ edited_point=wip.size();
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close(true);
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ if (poly.size() < 3) {
+
+ undo_redo->create_action("Edit Poly");
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ poly.push_back(cpoint);
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ //search edges
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 points[2] ={ xform.xform(poly[i]),
+ xform.xform(poly[(i+1)%poly.size()]) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+ if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
+ edited_point=closest_idx+1;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ node->get_occluder_polygon()->set_polygon(Variant(poly));
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ edited_point=closest_idx;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly[edited_point]=edited_point_pos;
+ undo_redo->create_action("Edit Poly");
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",pre_move_edit);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+
+ undo_redo->create_action("Edit Poly (Remove Point)");
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ }
+
+
+
+ } break;
+ }
+
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=snap_point(cpoint);
+ edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ }
+
+ } break;
+ }
+
+ return false;
+}
+void LightOccluder2DEditor::_canvas_draw() {
+
+ if (!node || !node->get_occluder_polygon().is_valid())
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ Vector<Vector2> poly;
+
+ if (wip_active)
+ poly=wip;
+ else
+ poly=Variant(node->get_occluder_polygon()->get_polygon());
+
+
+ Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
+
+ int len = poly.size();
+
+ for(int i=0;i<poly.size();i++) {
+
+
+ Vector2 p,p2;
+ p = i==edited_point ? edited_point_pos : poly[i];
+ if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
+ p2=edited_point_pos;
+ else
+ p2 = poly[(i+1)%poly.size()];
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ Color col=Color(1,0.3,0.1,0.8);
+
+ if (i==poly.size()-1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) {
+
+ } else {
+ vpc->draw_line(point,next_point,col,2);
+ }
+ vpc->draw_texture(handle,point-handle->get_size()*0.5);
+ }
+}
+
+
+
+void LightOccluder2DEditor::edit(Node *p_collision_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton();
+ }
+
+ if (p_collision_polygon) {
+
+ node=p_collision_polygon->cast_to<LightOccluder2D>();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+ canvas_item_editor->get_viewport_control()->update();
+ } else {
+ node=NULL;
+
+ if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
+
+ }
+
+}
+
+void LightOccluder2DEditor::_create_poly() {
+
+ if (!node)
+ return;
+ undo_redo->create_action("Create Occluder Polygon");
+ undo_redo->add_do_method(node,"set_occluder_polygon",Ref<OccluderPolygon2D>(memnew( OccluderPolygon2D)));
+ undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF()));
+ undo_redo->commit_action();
+}
+
+void LightOccluder2DEditor::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("_menu_option"),&LightOccluder2DEditor::_menu_option);
+ ObjectTypeDB::bind_method(_MD("_canvas_draw"),&LightOccluder2DEditor::_canvas_draw);
+ ObjectTypeDB::bind_method(_MD("_node_removed"),&LightOccluder2DEditor::_node_removed);
+ ObjectTypeDB::bind_method(_MD("_create_poly"),&LightOccluder2DEditor::_create_poly);
+
+}
+
+
+LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) {
+
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ add_child( memnew( VSeparator ));
+ button_create = memnew( ToolButton );
+ add_child(button_create);
+ button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+ button_create->set_tooltip("Create a new polygon from scratch");
+
+ button_edit = memnew( ToolButton );
+ add_child(button_edit);
+ button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.");
+
+ create_poly = memnew( ConfirmationDialog );
+ add_child(create_poly);
+ create_poly->get_ok()->set_text("Create");
+
+
+ //add_constant_override("separation",0);
+
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCODE",PARSE_BBCODE);
+ options->get_popup()->connect("item_pressed", this,"_menu_option");
+#endif
+
+ mode = MODE_EDIT;
+ wip_active=false;
+
+}
+
+
+void LightOccluder2DEditorPlugin::edit(Object *p_object) {
+
+ collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool LightOccluder2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("LightOccluder2D");
+}
+
+void LightOccluder2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ collision_polygon_editor->show();
+ } else {
+
+ collision_polygon_editor->hide();
+ collision_polygon_editor->edit(NULL);
+ }
+
+}
+
+LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ collision_polygon_editor = memnew( LightOccluder2DEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+ collision_polygon_editor->hide();
+
+
+
+}
+
+
+LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin()
+{
+}
+
diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.h b/tools/editor/plugins/light_occluder_2d_editor_plugin.h
new file mode 100644
index 0000000000..5fb5631d05
--- /dev/null
+++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.h
@@ -0,0 +1,87 @@
+#ifndef LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
+#define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
+
+
+
+#include "tools/editor/editor_plugin.h"
+#include "tools/editor/editor_node.h"
+#include "scene/2d/light_occluder_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class LightOccluder2DEditor : public HBoxContainer {
+
+ OBJ_TYPE(LightOccluder2DEditor, HBoxContainer );
+
+ UndoRedo *undo_redo;
+ enum Mode {
+
+ MODE_CREATE,
+ MODE_EDIT,
+
+ };
+
+ Mode mode;
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ LightOccluder2D *node;
+ MenuButton *options;
+
+ int edited_point;
+ Vector2 edited_point_pos;
+ Vector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+
+ ConfirmationDialog *create_poly;
+
+ void _wip_close(bool p_closed);
+ void _canvas_draw();
+ void _menu_option(int p_option);
+ void _create_poly();
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ Vector2 snap_point(const Vector2& p_point) const;
+ bool forward_input_event(const InputEvent& p_event);
+ void edit(Node *p_collision_polygon);
+ LightOccluder2DEditor(EditorNode *p_editor);
+};
+
+class LightOccluder2DEditorPlugin : public EditorPlugin {
+
+ OBJ_TYPE( LightOccluder2DEditorPlugin, EditorPlugin );
+
+ LightOccluder2DEditor *collision_polygon_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); }
+
+ virtual String get_name() const { return "LightOccluder2D"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_node);
+ virtual bool handles(Object *p_node) const;
+ virtual void make_visible(bool p_visible);
+
+ LightOccluder2DEditorPlugin(EditorNode *p_node);
+ ~LightOccluder2DEditorPlugin();
+
+};
+
+#endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
index 2a32a2216a..bc15741d0f 100644
--- a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -36,6 +36,9 @@ void NavigationPolygonEditor::_node_removed(Node *p_node) {
void NavigationPolygonEditor::_create_nav() {
+ if (!node)
+ return;
+
undo_redo->create_action("Create Navigation Polygon");
undo_redo->add_do_method(node,"set_navigation_polygon",Ref<NavigationPolygon>(memnew( NavigationPolygon)));
undo_redo->add_undo_method(node,"set_navigation_polygon",Variant(REF()));
@@ -96,7 +99,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) {
create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?");
create_nav->popup_centered_minsize();
}
- return false;
+ return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);;
}
@@ -434,6 +437,7 @@ void NavigationPolygonEditor::edit(Node *p_collision_polygon) {
wip.clear();
wip_active=false;
edited_point=-1;
+ canvas_item_editor->get_viewport_control()->update();
} else {
node=NULL;
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 1349d5ccab..72b3025f2f 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -630,11 +630,13 @@ bool ScriptEditor::_test_script_times_on_disk() {
- if (!all_ok)
- if (bool(EDITOR_DEF("text_editor/auto_reload_changed_scripts",false)))
+ if (!all_ok) {
+ if (bool(EDITOR_DEF("text_editor/auto_reload_changed_scripts",false))) {
script_editor->_reload_scripts();
- else
+ } else {
disk_changed->call_deferred("popup_centered_ratio",0.5);
+ }
+ }
return all_ok;
}
@@ -920,7 +922,7 @@ void ScriptEditor::_menu_option(int p_option) {
String line_text = tx->get_line(i);
if (line_text.begins_with("#"))
- line_text = line_text.strip_edges().substr(1, line_text.length());
+ line_text = line_text.substr(1, line_text.length());
else
line_text = "#" + line_text;
tx->set_line(i, line_text);
@@ -932,7 +934,7 @@ void ScriptEditor::_menu_option(int p_option) {
String line_text = tx->get_line(begin);
if (line_text.begins_with("#"))
- line_text = line_text.strip_edges().substr(1, line_text.length());
+ line_text = line_text.substr(1, line_text.length());
else
line_text = "#" + line_text;
tx->set_line(begin, line_text);
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
index 87bd8105af..30ac50057f 100644
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ b/tools/editor/plugins/spatial_editor_plugin.cpp
@@ -477,6 +477,16 @@ void SpatialEditorViewport::_select_region() {
}
+void SpatialEditorViewport::_update_name() {
+
+ String ortho = orthogonal?"Orthogonal":"Perspective";
+
+ if (name!="")
+ view_menu->set_text("[ "+name+" "+ortho+" ]");
+ else
+ view_menu->set_text("[ "+ortho+" ]");
+}
+
void SpatialEditorViewport::_compute_edit(const Point2& p_point) {
@@ -832,6 +842,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
_edit.plane=TRANSFORM_X_AXIS;
set_message("View Plane Transform.",2);
+ name="";
+ _update_name();
} break;
case TRANSFORM_X_AXIS: {
@@ -1460,6 +1472,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
cursor.x_rot=Math_PI/2.0;
if (cursor.x_rot<-Math_PI/2.0)
cursor.x_rot=-Math_PI/2.0;
+ name="";
+ _update_name();
} break;
default: {}
@@ -1484,9 +1498,14 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
if (k.mod.shift) {
cursor.x_rot=-Math_PI/2.0;
set_message("Bottom View.",2);
+ name="Bottom";
+ _update_name();
+
} else {
cursor.x_rot=Math_PI/2.0;
set_message("Top View.",2);
+ name="Top";
+ _update_name();
}
} break;
case KEY_KP_1: {
@@ -1495,10 +1514,14 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
if (k.mod.shift) {
cursor.y_rot=Math_PI;
set_message("Rear View.",2);
+ name="Rear";
+ _update_name();
} else {
cursor.y_rot=0;
set_message("Front View.",2);
+ name="Front";
+ _update_name();
}
} break;
@@ -1508,9 +1531,13 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
if (k.mod.shift) {
cursor.y_rot=Math_PI/2.0;
set_message("Left View.",2);
+ name="Left";
+ _update_name();
} else {
cursor.y_rot=-Math_PI/2.0;
set_message("Right View.",2);
+ name="Right";
+ _update_name();
}
} break;
@@ -1518,6 +1545,7 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
orthogonal = !orthogonal;
_menu_option(orthogonal?VIEW_PERSPECTIVE:VIEW_ORTHOGONAL);
+ _update_name();
} break;
@@ -1831,35 +1859,47 @@ void SpatialEditorViewport::_menu_option(int p_option) {
cursor.x_rot=Math_PI/2.0;
cursor.y_rot=0;
+ name="Top";
+ _update_name();
} break;
case VIEW_BOTTOM: {
cursor.x_rot=-Math_PI/2.0;
cursor.y_rot=0;
+ name="Bottom";
+ _update_name();
} break;
case VIEW_LEFT: {
cursor.y_rot=Math_PI/2.0;
cursor.x_rot=0;
+ name="Left";
+ _update_name();
} break;
case VIEW_RIGHT: {
cursor.y_rot=-Math_PI/2.0;
cursor.x_rot=0;
+ name="Right";
+ _update_name();
} break;
case VIEW_FRONT: {
cursor.y_rot=0;
cursor.x_rot=0;
+ name="Front";
+ _update_name();
} break;
case VIEW_REAR: {
cursor.y_rot=Math_PI;
cursor.x_rot=0;
+ name="Rear";
+ _update_name();
} break;
case VIEW_CENTER_TO_SELECTION: {
@@ -1941,6 +1981,7 @@ void SpatialEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false );
orthogonal=false;
call_deferred("update_transform_gizmo_view");
+ _update_name();
} break;
case VIEW_ORTHOGONAL: {
@@ -1949,6 +1990,7 @@ void SpatialEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true );
orthogonal=true;
call_deferred("update_transform_gizmo_view");
+ _update_name();
} break;
case VIEW_AUDIO_LISTENER: {
@@ -2147,15 +2189,13 @@ void SpatialEditorViewport::reset() {
message_time=0;
message="";
last_message="";
+ name="Top";
cursor.x_rot=0;
cursor.y_rot=0;
cursor.distance=4;
cursor.region_select=false;
-
-
-
-
+ _update_name();
}
SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
@@ -2189,18 +2229,17 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu = memnew( MenuButton );
surface->add_child(view_menu);
view_menu->set_pos( Point2(4,4));
- view_menu->set_text("[view]");
view_menu->set_self_opacity(0.5);
- view_menu->get_popup()->add_item("Top",VIEW_TOP);
- view_menu->get_popup()->add_item("Bottom",VIEW_BOTTOM);
- view_menu->get_popup()->add_item("Left",VIEW_LEFT);
- view_menu->get_popup()->add_item("Right",VIEW_RIGHT);
- view_menu->get_popup()->add_item("Front",VIEW_FRONT);
- view_menu->get_popup()->add_item("Rear",VIEW_REAR);
+ view_menu->get_popup()->add_item("Top (Num7)",VIEW_TOP);
+ view_menu->get_popup()->add_item("Bottom (Shift+Num7)",VIEW_BOTTOM);
+ view_menu->get_popup()->add_item("Left (Num3)",VIEW_LEFT);
+ view_menu->get_popup()->add_item("Right (Shift+Num3)",VIEW_RIGHT);
+ view_menu->get_popup()->add_item("Front (Num1)",VIEW_FRONT);
+ view_menu->get_popup()->add_item("Rear (Shift+Num1)",VIEW_REAR);
view_menu->get_popup()->add_separator();
- view_menu->get_popup()->add_check_item("Perspective",VIEW_PERSPECTIVE);
- view_menu->get_popup()->add_check_item("Orthogonal",VIEW_ORTHOGONAL);
+ view_menu->get_popup()->add_check_item("Perspective (Num5)",VIEW_PERSPECTIVE);
+ view_menu->get_popup()->add_check_item("Orthogonal (Num5)",VIEW_ORTHOGONAL);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE),true);
view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_item("Environment",VIEW_ENVIRONMENT);
@@ -2233,6 +2272,10 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
viewport->set_as_audio_listener(true);
}
+
+ name="Top";
+ _update_name();
+
EditorSettings::get_singleton()->connect("settings_changed",this,"update_transform_gizmo_view");
}
@@ -3666,7 +3709,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
p->add_check_item("View Origin",MENU_VIEW_ORIGIN);
p->add_check_item("View Grid",MENU_VIEW_GRID);
p->add_separator();
- p->add_check_item("Settings",MENU_VIEW_CAMERA_SETTINGS );
+ p->add_item("Settings",MENU_VIEW_CAMERA_SETTINGS);
p->set_item_checked( p->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), true );
diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h
index 646a4d2d86..4d594d1921 100644
--- a/tools/editor/plugins/spatial_editor_plugin.h
+++ b/tools/editor/plugins/spatial_editor_plugin.h
@@ -92,6 +92,7 @@ public:
};
private:
int index;
+ String name;
void _menu_option(int p_option);
Size2 prev_size;
@@ -110,6 +111,7 @@ private:
bool orthogonal;
float gizmo_scale;
+ void _update_name();
void _compute_edit(const Point2& p_point);
void _clear_selected();
void _select_clicked(bool p_append,bool p_single);
diff --git a/tools/editor/plugins/theme_editor_plugin.cpp b/tools/editor/plugins/theme_editor_plugin.cpp
index ccbd923118..bd6fb37b29 100644
--- a/tools/editor/plugins/theme_editor_plugin.cpp
+++ b/tools/editor/plugins/theme_editor_plugin.cpp
@@ -568,6 +568,26 @@ ThemeEditor::ThemeEditor() {
CheckButton *cb = memnew( CheckButton );
cb->set_text("CheckButton");
first_vb->add_child(cb );
+ CheckBox *cbx = memnew( CheckBox );
+ cbx->set_text("CheckBox");
+ first_vb->add_child(cbx );
+
+ /* TODO: This is not working properly, controls are overlapping*/
+ /*
+ ButtonGroup *bg = memnew( ButtonGroup );
+ bg->set_v_size_flags(SIZE_EXPAND_FILL);
+ VBoxContainer *gbvb = memnew( VBoxContainer );
+ gbvb->set_v_size_flags(SIZE_EXPAND_FILL);
+ CheckBox *rbx1 = memnew( CheckBox );
+ rbx1->set_text("CheckBox Radio1");
+ rbx1->set_pressed(true);
+ gbvb->add_child(rbx1);
+ CheckBox *rbx2 = memnew( CheckBox );
+ rbx2->set_text("CheckBox Radio2");
+ gbvb->add_child(rbx2);
+ bg->add_child(gbvb);
+ first_vb->add_child(bg);
+ */
MenuButton* test_menu_button = memnew( MenuButton );
test_menu_button->set_text("MenuButton");
diff --git a/tools/editor/plugins/theme_editor_plugin.h b/tools/editor/plugins/theme_editor_plugin.h
index 98156422ee..83432b9232 100644
--- a/tools/editor/plugins/theme_editor_plugin.h
+++ b/tools/editor/plugins/theme_editor_plugin.h
@@ -33,6 +33,8 @@
#include "scene/gui/texture_frame.h"
#include "scene/gui/option_button.h"
#include "scene/gui/file_dialog.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/button_group.h"
#include "tools/editor/editor_node.h"
diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp
index 47727a00c2..79e43f9012 100644
--- a/tools/editor/plugins/tile_map_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_map_editor_plugin.cpp
@@ -640,19 +640,53 @@ void TileMapEditor::_canvas_draw() {
Ref<Texture> t = ts->tile_get_texture(st);
if (t.is_valid()) {
- Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+node->map_to_world(over_tile)+node->get_cell_draw_offset());
+ Vector2 from = node->map_to_world(over_tile)+node->get_cell_draw_offset();
Rect2 r = ts->tile_get_region(st);
Size2 sc = xform.get_scale();
if (mirror_x->is_pressed())
sc.x*=-1.0;
if (mirror_y->is_pressed())
sc.y*=-1.0;
+
+ Rect2 rect;
+ if (r==Rect2()) {
+ rect=Rect2(from,t->get_size());
+ } else {
+
+ rect=Rect2(from,r.get_size());
+ }
+
+
+ if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) {
+ rect.pos+=ts->tile_get_texture_offset(st);
+
+ } else if (node->get_tile_origin()==TileMap::TILE_ORIGIN_CENTER) {
+ rect.pos+=node->get_cell_size()/2;
+ Vector2 s = r.size;
+
+ Vector2 center = (s/2) - ts->tile_get_texture_offset(st);
+
+
+ if (mirror_x->is_pressed())
+ rect.pos.x-=s.x-center.x;
+ else
+ rect.pos.x-=center.x;
+
+ if (mirror_y->is_pressed())
+ rect.pos.y-=s.y-center.y;
+ else
+ rect.pos.y-=center.y;
+ }
+
+ rect.pos=xform.xform(rect.pos);
+ rect.size*=sc;
+
if (r==Rect2()) {
- canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5),transpose->is_pressed());
+ canvas_item_editor->draw_texture_rect(t,rect,false,Color(1,1,1,0.5),transpose->is_pressed());
} else {
- canvas_item_editor->draw_texture_rect_region(t,Rect2(from,r.get_size()*sc),r,Color(1,1,1,0.5),transpose->is_pressed());
+ canvas_item_editor->draw_texture_rect_region(t,rect,r,Color(1,1,1,0.5),transpose->is_pressed());
}
}
}
diff --git a/tools/editor/plugins/tile_set_editor_plugin.cpp b/tools/editor/plugins/tile_set_editor_plugin.cpp
index a51caf7d54..8ff7720934 100644
--- a/tools/editor/plugins/tile_set_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_set_editor_plugin.cpp
@@ -37,83 +37,103 @@ void TileSetEditor::edit(const Ref<TileSet>& p_tileset) {
void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_merge) {
if (!p_merge)
- p_library->clear();
+ p_library->clear();
for(int i=0;i<scene->get_child_count();i++) {
- Node *child = scene->get_child(i);
+ Node *child = scene->get_child(i);
- if (!child->cast_to<Sprite>()) {
- if (child->get_child_count()>0) {
- child=child->get_child(0);
- if (!child->cast_to<Sprite>()) {
- continue;
- }
+ if (!child->cast_to<Sprite>()) {
+ if (child->get_child_count()>0) {
+ child=child->get_child(0);
+ if (!child->cast_to<Sprite>()) {
+ continue;
+ }
- } else
- continue;
+ } else
+ continue;
- }
+ }
- Sprite *mi = child->cast_to<Sprite>();
- Ref<Texture> texture=mi->get_texture();
- if (texture.is_null())
+ Sprite *mi = child->cast_to<Sprite>();
+ Ref<Texture> texture=mi->get_texture();
+ Ref<CanvasItemMaterial> material=mi->get_material();
+
+ if (texture.is_null())
continue;
- int id = p_library->find_tile_by_name(mi->get_name());
- if (id<0) {
-
- id=p_library->get_last_unused_tile_id();
- p_library->create_tile(id);
- p_library->tile_set_name(id,mi->get_name());
- }
-
-
- p_library->tile_set_texture(id,texture);
- Vector2 phys_offset;
-
- if (mi->is_centered()) {
- Size2 s;
- if (mi->is_region()) {
- s=mi->get_region_rect().size;
- } else {
- s=texture->get_size();
- }
- phys_offset+=-s/2;
- }
- if (mi->is_region()) {
- p_library->tile_set_region(id,mi->get_region_rect());
- }
-
- Vector<Ref<Shape2D> >collisions;
-
- for(int j=0;j<mi->get_child_count();j++) {
-
- Node *child2 = mi->get_child(j);
- if (!child2->cast_to<StaticBody2D>())
- continue;
- StaticBody2D *sb = child2->cast_to<StaticBody2D>();
- if (sb->get_shape_count()==0)
- continue;
- Ref<Shape2D> collision=sb->get_shape(0);
- if (collision.is_valid()) {
- collisions.push_back(collision);
+ int id = p_library->find_tile_by_name(mi->get_name());
+ if (id<0) {
+
+ id=p_library->get_last_unused_tile_id();
+ p_library->create_tile(id);
+ p_library->tile_set_name(id,mi->get_name());
+ }
+
+
+
+ p_library->tile_set_texture(id,texture);
+ p_library->tile_set_material(id,material);
+
+ Vector2 phys_offset;
+
+ if (mi->is_centered()) {
+ Size2 s;
+ if (mi->is_region()) {
+ s=mi->get_region_rect().size;
+ } else {
+ s=texture->get_size();
+ }
+ phys_offset+=-s/2;
+ }
+ if (mi->is_region()) {
+ p_library->tile_set_region(id,mi->get_region_rect());
+ }
+
+ Vector<Ref<Shape2D> >collisions;
+ Ref<NavigationPolygon> nav_poly;
+ Ref<OccluderPolygon2D> occluder;
+
+ for(int j=0;j<mi->get_child_count();j++) {
+
+ Node *child2 = mi->get_child(j);
+
+ if (child2->cast_to<NavigationPolygonInstance>())
+ nav_poly=child2->cast_to<NavigationPolygonInstance>()->get_navigation_polygon();
+
+ if (child2->cast_to<LightOccluder2D>())
+ occluder=child2->cast_to<LightOccluder2D>()->get_occluder_polygon();
+
+ if (!child2->cast_to<StaticBody2D>())
+ continue;
+ StaticBody2D *sb = child2->cast_to<StaticBody2D>();
+ if (sb->get_shape_count()==0)
+ continue;
+ Ref<Shape2D> collision=sb->get_shape(0);
+ if (collision.is_valid()) {
+ collisions.push_back(collision);
}
- }
+ }
- if (collisions.size()) {
+ if (collisions.size()) {
- p_library->tile_set_shapes(id,collisions);
- p_library->tile_set_shape_offset(id,-phys_offset);
- } else {
- p_library->tile_set_shape_offset(id,Vector2());
+ p_library->tile_set_shapes(id,collisions);
+ p_library->tile_set_shape_offset(id,-phys_offset);
+ } else {
+ p_library->tile_set_shape_offset(id,Vector2());
+
+ }
+
+ p_library->tile_set_texture_offset(id,mi->get_offset());
+ p_library->tile_set_navigation_polygon(id,nav_poly);
+ p_library->tile_set_light_occluder(id,occluder);
+ p_library->tile_set_occluder_offset(id,-phys_offset);
+ p_library->tile_set_navigation_polygon_offset(id,-phys_offset);
- }
- p_library->tile_set_texture_offset(id,mi->get_offset());
}
}
@@ -121,23 +141,23 @@ void TileSetEditor::_menu_confirm() {
switch(option) {
- case MENU_OPTION_REMOVE_ITEM: {
+ case MENU_OPTION_REMOVE_ITEM: {
- tileset->remove_tile(to_erase);
- } break;
- case MENU_OPTION_MERGE_FROM_SCENE:
- case MENU_OPTION_CREATE_FROM_SCENE: {
+ tileset->remove_tile(to_erase);
+ } break;
+ case MENU_OPTION_MERGE_FROM_SCENE:
+ case MENU_OPTION_CREATE_FROM_SCENE: {
- EditorNode *en = editor;
- Node * scene = en->get_edited_scene();
- if (!scene)
- break;
+ EditorNode *en = editor;
+ Node * scene = en->get_edited_scene();
+ if (!scene)
+ break;
- _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE);
+ _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE);
- } break;
+ } break;
}
}
@@ -165,11 +185,11 @@ void TileSetEditor::_menu_cbk(int p_option) {
cd->set_text("Create from scene?");
cd->popup_centered(Size2(300,60));
} break;
- case MENU_OPTION_MERGE_FROM_SCENE: {
+ case MENU_OPTION_MERGE_FROM_SCENE: {
- cd->set_text("Merge from scene?");
- cd->popup_centered(Size2(300,60));
- } break;
+ cd->set_text("Merge from scene?");
+ cd->popup_centered(Size2(300,60));
+ } break;
}
}
diff --git a/tools/editor/plugins/tile_set_editor_plugin.h b/tools/editor/plugins/tile_set_editor_plugin.h
index 2531ec55bf..1248b4e007 100644
--- a/tools/editor/plugins/tile_set_editor_plugin.h
+++ b/tools/editor/plugins/tile_set_editor_plugin.h
@@ -56,7 +56,7 @@ class TileSetEditor : public Control {
int option;
void _menu_cbk(int p_option);
- void _menu_confirm();
+ void _menu_confirm();
static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge);
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index a600683097..078a177ca1 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -651,6 +651,8 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty
if (!RES(v).is_null()) {
+
+
menu->add_icon_item(get_icon("EditResource","EditorIcons"),"Edit",OBJ_MENU_EDIT);
menu->add_icon_item(get_icon("Del","EditorIcons"),"Clear",OBJ_MENU_CLEAR);
menu->add_icon_item(get_icon("Duplicate","EditorIcons"),"Make Unique",OBJ_MENU_MAKE_UNIQUE);
@@ -659,6 +661,13 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty
menu->add_separator();
menu->add_icon_item(get_icon("Reload","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT);
}
+ /*if (r.is_valid() && r->get_path().is_resource_file()) {
+ menu->set_item_tooltip(1,r->get_path());
+ } else if (r.is_valid()) {
+ menu->set_item_tooltip(1,r->get_name()+" ("+r->get_type()+")");
+ }*/
+ } else {
+
}
@@ -1857,8 +1866,41 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p
} else {
p_item->set_text(1,"<"+res->get_type()+">");
};
+
+
+ if (res.is_valid() && res->get_path().is_resource_file()) {
+ p_item->set_tooltip(1,res->get_path());
+ } else if (res.is_valid()) {
+ p_item->set_tooltip(1,res->get_name()+" ("+res->get_type()+")");
+ }
+
+
+ if (has_icon(res->get_type(),"EditorIcons")) {
+
+ p_item->set_icon(0,get_icon(res->get_type(),"EditorIcons"));
+ } else {
+
+ Dictionary d = p_item->get_metadata(0);
+ int hint=d.has("hint")?d["hint"].operator int():-1;
+ String hint_text=d.has("hint_text")?d["hint_text"]:"";
+ if (hint==PROPERTY_HINT_RESOURCE_TYPE) {
+
+ if (has_icon(hint_text,"EditorIcons")) {
+
+ p_item->set_icon(0,get_icon(hint_text,"EditorIcons"));
+
+ } else {
+ p_item->set_icon(0,get_icon("Object","EditorIcons"));
+
+ }
+ }
+ }
+
+
+
}
+
} break;
default: {};
}
@@ -2337,7 +2379,7 @@ void PropertyEditor::update_tree() {
} else {
if (p.type == Variant::REAL) {
- item->set_range_config(1, -65536, 65535, 0.01);
+ item->set_range_config(1, -65536, 65535, 0.001);
} else {
item->set_range_config(1, -65536, 65535, 1);
@@ -2529,7 +2571,10 @@ void PropertyEditor::update_tree() {
item->set_editable( 1, !read_only );
item->add_button(1,get_icon("EditResource","EditorIcons"));
String type;
+ if (p.hint==PROPERTY_HINT_RESOURCE_TYPE)
+ type=p.hint_string;
bool notnil=false;
+
if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) {
item->set_text(1,"<null>");
@@ -2553,12 +2598,25 @@ void PropertyEditor::update_tree() {
};
notnil=true;
+ if (has_icon(res->get_type(),"EditorIcons")) {
+ type=res->get_type();
+ }
+
+ if (res.is_valid() && res->get_path().is_resource_file()) {
+ item->set_tooltip(1,res->get_path());
+ } else if (res.is_valid()) {
+ item->set_tooltip(1,res->get_name()+" ("+res->get_type()+")");
+ }
+
}
- if (p.hint==PROPERTY_HINT_RESOURCE_TYPE) {
+
+ if (type!=String()) {
+ if (type.find(",")!=-1)
+ type=type.get_slice(",",0);
//printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data());
- if (has_icon(p.hint_string,"EditorIcons"))
- item->set_icon( 0, get_icon(p.hint_string,"EditorIcons") );
+ if (has_icon(type,"EditorIcons"))
+ item->set_icon( 0, get_icon(type,"EditorIcons") );
else
item->set_icon( 0, get_icon("Object","EditorIcons") );
}
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py
index 8e751fc33c..5e5febfb1f 100644
--- a/tools/export/blender25/io_scene_dae/export_dae.py
+++ b/tools/export/blender25/io_scene_dae/export_dae.py
@@ -94,8 +94,6 @@ def strarr(arr):
s+=" "
return s
-
-
class DaeExporter:
def validate_id(self,d):
@@ -132,10 +130,10 @@ class DaeExporter:
tup = tup + (self.tangent.x,self.tangent.y,self.tangent.z)
if (self.bitangent!=None):
tup = tup + (self.bitangent.x,self.bitangent.y,self.bitangent.z)
- #for t in self.bones:
- # tup = tup + (t)
- #for t in self.weights:
- # tup = tup + (t)
+ for t in self.bones:
+ tup = tup + (float(t),)
+ for t in self.weights:
+ tup = tup + (float(t),)
return tup
@@ -512,12 +510,12 @@ class DaeExporter:
mat_assign=[]
uv_layer_count=len(mesh.uv_textures)
- if (len(mesh.uv_textures)):
+ if (has_tangents and 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
+ self.operator.report({'WARNING'},'CalcTangets failed for mesh "'+mesh.name+'", no tangets will be exported.')
+ #uv_layer_count=0
mesh.calc_normals_split()
has_tangents=False
@@ -591,16 +589,30 @@ class DaeExporter:
if (armature!=None):
wsum=0.0
+ zero_bones=[]
+
for vg in mv.groups:
if vg.group >= len(node.vertex_groups):
continue;
name = node.vertex_groups[vg.group].name
+
if (name in si["bone_index"]):
#could still put the weight as 0.0001 maybe
if (vg.weight>0.001): #blender has a lot of zero weight stuff
v.bones.append(si["bone_index"][name])
v.weights.append(vg.weight)
wsum+=vg.weight
+ if (wsum==0.0):
+ if not self.wrongvtx_report:
+ self.operator.report({'WARNING'},'Mesh for object "'+node.name+'" has unassigned weights. This may look wrong in exported model.')
+ self.wrongvtx_report=True
+
+ #blender can have bones assigned that weight zero so they remain local
+ #this is the best it can be done?
+ v.bones.append(0)
+ v.weights.append(1)
+
+
tup = v.get_tup()
@@ -889,6 +901,15 @@ class DaeExporter:
if (node.parent!=None):
if (node.parent.type=="ARMATURE"):
armature=node.parent
+ armcount=0
+ for n in node.modifiers:
+ if (n.type=="ARMATURE"):
+ armcount+=1
+ if (armcount>1):
+ self.operator.report({'WARNING'},'Object "'+node.name+'" refers to more than one armature! This is unsopported.')
+
+
+
if (node.data.shape_keys!=None):
sk = node.data.shape_keys
@@ -940,6 +961,12 @@ class DaeExporter:
boneidx = si["bone_count"]
si["bone_count"]+=1
bonesid = si["id"]+"-"+str(boneidx)
+ if (bone.name in self.used_bones):
+ if (self.config["use_anim_action_all"]):
+ self.operator.report({'WARNING'},'Bone name "'+bone.name+'" used in more than one skeleton. Actions might export wrong.')
+ else:
+ self.used_bones.append(bone.name)
+
si["bone_index"][bone.name]=boneidx
si["bone_ids"][bone]=boneid
si["bone_names"].append(bonesid)
@@ -1002,12 +1029,12 @@ class DaeExporter:
self.writel(S_CAMS,5,'<zfar> '+str(camera.clip_end)+' </zfar>')
self.writel(S_CAMS,4,'</perspective>')
else:
- self.writel(S_CAMS,4,'<orthografic>')
- self.writel(S_CAMS,5,'<xmag> '+str(camera.ortho_scale)+' </xmag>') # I think?
+ self.writel(S_CAMS,4,'<orthographic>')
+ self.writel(S_CAMS,5,'<xmag> '+str(camera.ortho_scale*0.5)+' </xmag>') # I think?
self.writel(S_CAMS,5,'<aspect_ratio> '+str(self.scene.render.resolution_x / self.scene.render.resolution_y)+' </aspect_ratio>')
self.writel(S_CAMS,5,'<znear> '+str(camera.clip_start)+' </znear>')
self.writel(S_CAMS,5,'<zfar> '+str(camera.clip_end)+' </zfar>')
- self.writel(S_CAMS,4,'</orthografic>')
+ self.writel(S_CAMS,4,'</orthographic>')
self.writel(S_CAMS,3,'</technique_common>')
self.writel(S_CAMS,2,'</optics>')
@@ -1534,10 +1561,14 @@ class DaeExporter:
for z in tcn:
self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'"/>')
self.writel(S_ANIM_CLIPS,1,'</animation_clip>')
+ if (len(tcn)==0):
+ self.operator.report({'WARNING'},'Animation clip "'+x.name+'" contains no tracks.')
+
self.writel(S_ANIM_CLIPS,0,'</library_animation_clips>')
+
for i,s in enumerate(self.skeletons):
if (s.animation_data==None):
continue
@@ -1547,6 +1578,7 @@ class DaeExporter:
s.animation_data.action = None
for j,bone in enumerate(s.pose.bones):
bone.matrix_basis = tmp_mat[i][1][j]
+
else:
self.export_animation(self.scene.frame_start,self.scene.frame_end)
@@ -1617,7 +1649,8 @@ class DaeExporter:
f.write(bytes('</COLLADA>\n',"UTF-8"))
return True
- def __init__(self,path,kwargs):
+ def __init__(self,path,kwargs,operator):
+ self.operator=operator
self.scene=bpy.context.scene
self.last_id=0
self.scene_name=self.new_id("scene")
@@ -1631,6 +1664,10 @@ class DaeExporter:
self.config=kwargs
self.valid_nodes=[]
self.armature_for_morph={}
+ self.used_bones=[]
+ self.wrongvtx_report=False
+
+
@@ -1642,9 +1679,11 @@ def save(operator, context,
**kwargs
):
- exp = DaeExporter(filepath,kwargs)
+ exp = DaeExporter(filepath,kwargs,operator)
exp.export()
+
+
return {'FINISHED'} # so the script wont run after we have batch exported.
diff --git a/tools/script_plugins/time/time.gd b/tools/script_plugins/time/time.gd
index 66b3e9ed04..2e56d89d4f 100644
--- a/tools/script_plugins/time/time.gd
+++ b/tools/script_plugins/time/time.gd
@@ -21,12 +21,12 @@ func _init():
timer.set_one_shot(false)
timer.connect("timeout",self,"_timeout")
-func _enter_scene():
+func _enter_tree():
label = Label.new()
add_custom_control(CONTAINER_TOOLBAR,label)
timer.start()
-func _exit_scene():
+func _exit_tree():
timer.stop()
label.free()
label=null